連続する数列をハイフンでまとめるPythonスクリプト

連続する数列をハイフンでまとめるシェルスクリプト – ザリガニが見ていた…。を見て、面白いことをやっているので Python でやってみた。

 cf. Rubyでどう書く?:連続した数列を範囲形式にまとめたい – builder by ZDNet Japan (元記事)

def diff(a):
    return map(lambda x, y: x - y, a[1:], a[:-1])

def hyphenate_num(s):
    a = map(lambda x: int(x), s.split())
    d = diff(a)
    b = map(lambda x, y: (x, y), a, d)
    r = []
    flg = False
    for x in b:
        if x[1] > 1:
            r.append(str(x[0]))
            r.append(', ')
            flg = False
        elif x[1] == 1:
            if not flg:
                r.append(str(x[0]))
                r.append('-')
                flg = True
        else:
            r.append(str(x[0]))
    return ''.join(r)

if __name__ == '__main__':
    print hyphenate_num("1 2 3")
    print hyphenate_num("1 2 3 5 7 8")
    print hyphenate_num("1 3 4 5 7")

実行結果:

^o^ > python hyphenate_num.py
1-3
1-3, 5, 7-8
1, 3-5, 7

あんまりきれいなコードじゃないけどできた。やっぱりreduceを使うのほうがいいのかなあ。

「連続する数列をハイフンでまとめるPythonスクリプト」への3件のフィードバック

  1. 挑戦してみましたが、
    なかなかエレガントかつわかりやすく書くのは難しいですね。。

    from itertools import groupby,chain

    unpackdiff = lambda (x,y):x-y

    def hyphenate(s):
    nums = map(int,s.split())
    for diff, g in groupby(zip(nums,nums[1:]),unpackdiff):
    seqs = list(g)
    if diff == -1:
    yield seqs[0][0],’-‘,seqs[-1][1]
    else :
    yield chain(*((a,’, ‘,b) for a, b in seqs))

    def create_hyphenated(s):
    return ”.join(str(k) for k,_ in groupby(chain(*hyphenate(s))))

    if __name__ == ‘__main__’:
    print create_hyphenated(“1 2 3”)
    print create_hyphenated(“1 2 3 5 7 8”)
    print create_hyphenated(“1 3 4 5 7”)

    使っているパーツは違いますが、
    基本的な考え方は大きくは変わらないかと思います。
    工夫と言えばgroupbyを使った重複削除くらいでしょうか。

    余談ですが、
    map(lambda x: int(x), s.split()) は単に map(int, s.split())、
    map(lambda x, y: (x, y), a, d) は単にzip(a,d)
    とすれば、よりすっきりすると思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください