defmerge_sort(arr): return arr iflen(arr) <= 1elseNoneif (l := merge_sort(arr[:len(arr)//2])) and (r := merge_sort(arr[len(arr)//2:])) andFalseelse [l.pop(0) if l and r and l[0]<=r[0] else (r.pop(0) if r else l.pop(0)) for _ inrange(len(arr))]
みやすく
1 2 3 4 5 6 7 8 9
defmerge_sort(arr): return arr iflen(arr) <= 1 \ elseNoneif (l := merge_sort(arr[:len(arr)//2])) \ and (r := merge_sort(arr[len(arr)//2:])) \ andFalse \ else [ l.pop(0) if l and r and l[0]<=r[0] else (r.pop(0) if r else l.pop(0)) for _ inrange(len(arr)) ]
解説
展開すると以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12
defmerge_sort(arr):
# 再帰の終了条件 iflen(arr) <= 1: return arr # left, rightに分割 l = merge_sort(arr[:len(arr)//2]) r = merge_sort(arr[len(arr)//2:])
# mergeする return [l.pop(0) if l and r and l[0]<=r[0] else (r.pop(0) if r else l.pop(0)) for _ inrange(len(arr))]
# mergeの原型 res = [] while l and r: if l[0] <= r[0]: res.append( l.pop(0) ) else: res.append( r.pop(0) ) res += l + r
# for文で書き換え res = [] for _ inrange(len(l) + len(r)): if l and r and l[0] <= r[0]: res.append( l.pop(0) ) elif r: res.append( r.pop(0) ) else: res.append( l.pop(0) ) # lだけに残っている場合
# 内包表記にまとめる [l.pop(0) if l and r and l[0]<=r[0] else (r.pop(0) if r else l.pop(0)) for _ inrange(len(arr))]
また、下のような謎の式が入っているのは
1 2 3 4
... if (l := merge_sort(arr[:len(arr)//2])) \ and (r := merge_sort(arr[len(arr)//2:])) \ andFalse \ else ...