0

私は次のようなデータを持っています

[2, 2, 2, 2, 2, 3, 13, 113]

次に、自分で生成したキーで個別のリストに並べ替えたいと思います。実際、可能なすべてのリストを生成したいと考えています。

いくつかの例:

values: [2, 2, 2, 2, 2, 3, 13, 113]
keys:   [0, 0, 1, 2, 1, 3,  3,   1]
sublists: [2, 2], [2, 2, 113], [2], [3, 13]

values: [2, 2, 2, 2, 2, 3, 13, 113]
keys:   [0, 1, 0, 0, 0, 1,  1,   0]
sublists: [2, 2, 2, 2, 113], [2, 3, 13]

values: [2, 2, 2, 2, 2, 3, 13, 113]
keys:   [2, 3, 0, 0, 4, 4,  1,   3]
sublists: [2, 2], [13], [2], [2, 113], [2, 3]

すべての可能なキーは、によって生成されます

def generate_keys(prime_factors):
    key_size = len(prime_factors) - 1
    key_values = [str(i) for i in range(key_size)]

    return list(itertools.combinations_with_replacement(key_values, \
        len(prime_factors)))

次に、キーを使用して値をサブリストにシフトできると考えました。それが私が立ち往生している部分です。私は itertools.groupby が私の解決策になると思っていましたが、さらに調査すると、カスタムリストを groupby のキーとして使用する方法がわかりません。

これらのキーを使用して、大きなリストを小さなサブリストに分割するにはどうすればよいですか? キーを使用せずにこれを行う方法さえあるかもしれません。いずれにせよ、私はそれを行う方法がわかりません.他のスタックオーバーフローの質問を見ると、球場にエベンがありますが、正確にはこの質問ではありません.

4

1 に答える 1

3

これはあなたが望むことをします:

def sift(keys, values):
    answer = collections.defaultdict(list)
    kvs = zip(keys, values)
    for k,v in kvs:
        answer[k].append(v)
    return [answer[k] for k in sorted(answer)]

In [205]: keys = [0, 0, 1, 2, 1, 3,  3,   1]

In [206]: values = [2, 2, 2, 2, 2, 3, 13, 113]

In [207]: sift(keys,values)
Out[207]: [[2, 2], [2, 2, 113], [2], [3, 13]]

説明:

collections.defaultdictdictは、操作しようとしているディクショナリにキーが存在しない場合にどうするかを定義できる便利な のようなクラスです。たとえば、私のコードでは、answer[k].append(v). それappendlist関数であることはわかっているので、それはanswer[k]リストでなければならないこともわかっています。ただし、従来のキーを使用していて、存在しないキーの値を取得dictしようとすると、次のようになります。appendKeyError

In [212]: d = {}

In [213]: d[1] = []

In [214]: d
Out[214]: {1: []}

In [215]: d[1].append('one')

In [216]: d[1]
Out[216]: ['one']

In [217]: d
Out[217]: {1: ['one']}

In [218]: d[2].append('two')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/Users/USER/<ipython-input-218-cc58f739eefa> in <module>()
----> 1 d[2].append('two')

KeyError: 2

これは、定義したからこそ可能になったものanswer = collections.defaultdict(list)です。を定義answer = collections.defaultdict(int)していた場合は、別のエラーが発生します。intオブジェクトにメソッドがないことを示すエラーappendです。

zip一方、 は 2 つlist(実際には、少なくとも 2 つ必要です) を取り、それらを呼び出して、2 つiterableオブジェクトを含むタプルのリストを返します。1 つ目はで、2 つ目はです。との長さが等しくない場合、 は と の中で小さい方の値になります(つまり.list1list2ilist1[i]list2[i]list1list2len(zip(list1, list2))len(list1)len(list2)min(len(list1), len(list2))

keysと を圧縮したら、 からの値を からの値のリストにvaluesマップするような dict を作成したいと思います。これが、値に追加する前にキーの存在を確認する必要がないように、 を使用した理由です。従来の dict を使用していた場合、次のようにする必要がありました。keysvaluesdefaultdict

answer = {}
kvs = zip(keys, values)
for k,v, in kvs:
    if k in answer:
        answer[k].append(v)
    else:
        answer[k] = [v]

からの値を同じキーを共有する のリストにマップするdict(または のdictようなオブジェクト)ができたので、あとは のキーでソートされたの値であるリストを取得するだけです。すべてのs キーのリストをソート順に表示します。keysintansweranswersorted(answer)answer

この並べ替えられたキーのリストを取得したら、あとは int のリストであるそれらの値を取得し、それらすべてのリストを 1 つの大きなリストに入れ、その大きなリストを返すだけです。

… アナウンス 完了!それが役立つことを願っています

于 2012-10-17T00:04:13.470 に答える