18

十数回の for ループがこの問題の解決策ではないことは確かなので、私はそれに苦労しています。

次のような数字のソートされたリストがあります

numbers = [123, 124, 128, 160, 167, 213, 215, 230, 245, 255, 257, 400, 401, 402, 430]

そして、数字のリストを使用してdictを作成したいのですが、数字の違い(互いに続く)は15以下です。したがって、出力は次のようになります。

clusters = {
    1 : [123, 124, 128],
    2 : [160, 167],
    3 : [213, 215, 230, 245, 255, 257],
    4 : [400, 401, 402],
    5 : [430]
}

私の現在の解決策は少し醜いです(最後に重複を削除する必要があります…)、Pythonicの方法で実行できると確信しています。

これは私が今していることです:

clusters = {}  
dIndex = 0 
for i in range(len(numbers)-1) :
    if numbers[i+1] - numbers[i] <= 15 :
        if not clusters.has_key(dIndex) : clusters[dIndex] = []
        clusters[dIndex].append(numbers[i])
        clusters[dIndex].append(numbers[i+1])
    else : dIndex += 1
4

5 に答える 5

2

ジェネレーターを使用してロジックを分離する: (1 つの関数が 1 つのことを行う)

numbers = [123, 124, 128, 160, 167, 213, 215, 230, 245, 255, 257, 400, 401, 402, 430]

def cut_indices(numbers):
    # this function iterate over the indices that need to be 'cut'
    for i in xrange(len(numbers)-1):
        if numbers[i+1] - numbers[i] > 15:
            yield i+1

def splitter(numbers):
    # this function split the original list into sublists.
    px = 0
    for x in cut_indices(numbers):
        yield numbers[px:x]
        px = x
    yield numbers[px:]

def cluster(numbers):
    # using the above result, to form a dict object.
    cluster_ids = xrange(1,len(numbers))
    return dict(zip(cluster_ids, splitter(numbers)))

print cluster(numbers)

上記のコードは私に与えます

{1: [123, 124, 128], 2: [160, 167], 3: [213, 215, 230, 245, 255, 257], 4: [400, 401, 402], 5: [430]}
于 2013-04-04T01:58:09.523 に答える
1

リストまたはジェネレーターで機能する比較的単純なソリューションを次に示します。遅延してペアが生成(group_number, element)されるため、必要に応じて実際のグループ化を個別に行う必要があります。(または、グループ番号だけが必要な場合もあります。)

 from itertools import tee

 def group(xs, gap=15):
    # use `tee` to get two efficient iterators
    xs1, xs2 = tee(xs)

    # the first element is in group 0, also advance the second iterator
    group = 0
    yield (group, next(xs2))

    # after advancing xs2, this zip is pairs of consecutive elements
    for x, y in zip(xs1, xs2):
        # whenever the gap is too large, increment the group number
        if y - x > gap:
            group += 1
        # and yield the second number in the pair
        yield group, y
于 2016-04-01T23:20:07.400 に答える