compact-number-list
def compact_number_list(L): if len(L) < 2: return L L2 = [[L[0]]] for i, v in enumerate(L[1:]): if L2[-1][-1] + 1 == v: L2[-1].append(v) else: L2.append([v]) L3 = [] for vs in L2: if len(vs) == 1: L3.append(vs[0]) else: L3.append([vs[0], vs[-1]]) return L3 print compact_number_list([1, 3, 4, 5, 6, 12, 13, 15]) #=> [1, [3, 6], [12, 13], 15]
結局CortYumingさんと同じアルゴリズムになってしまった。別解や昨日の発展問題はあとでまた考えるつもり。
追記(2008/9/28):
itertools.groupbyを使った方法。あと3項演算子使ってみた。
from itertools import groupby def compact_number_list(L): def kf(x): if kf.prev: if kf.prev+1 == x: kf.prev = x return kf.cnt else: kf.cnt += 1 kf.prev = x return kf.cnt else: kf.prev = x return kf.cnt kf.prev = None kf.cnt = 1 L2 = [] for k, g in groupby(L, kf): L_ = list(g) is_not_scalar = len(L_)!=1 L_ = [L_[0], L_[-1]][0:[1, 2][is_not_scalar]] L2.extend([L_, [L_]][is_not_scalar]) return L2 print compact_number_list([1, 3, 4, 5, 6, 12, 13, 15]) #=> [1, [3, 6], [12, 13], 15]
groupbyは以下のようにkf(x)の値が同じになるxをグループ分けする。
kf(x) [x] ------------------- 1 [1] 2 [3, 4, 5, 6] 3 [12, 13] 4 [15]
3項演算子は以下の3通りやり方がある。
a if is_a else b # 2.5以上 is_a and a or b # aの部分がNoneやFalseになる場合 # [is_a and [a] or [b]][0]のようにリストかタプルでくくる必要がある # もしくは、[res] = is_a and [a] or [b] [a, b][is_not_a] # False==0, True==1であることを利用している