web-dev-qa-db-ja.com

Pythonで空のリストのリストまたはタプルを作成する方法は?

リストまたはリストのタプルを段階的に埋める必要があります。次のようなもの:

_result = []
firstTime = True
for i in range(x):
    for j in someListOfElements:
        if firstTime:
            result.append([f(j)])
        else:
            result[i].append(j)
_

それをより簡潔に、よりエレガントにするために、空のリストのリストを事前に割り当てると思いました

_result = createListOfEmptyLists(x)
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)
_

事前割り当ての部分は私には明らかではありません。 _result = [[]] * x_を実行すると、同じリストへのx参照のリストを受け取るため、次の出力が

_result[0].append(10)
print result
_

は:

_[[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]]
_

ループ(result = [[] for i in range(x)])を使用できますが、「ループレス」ソリューションが存在するかどうか疑問に思います。

私が探しているものを手に入れる唯一の方法です

40
Boris Gorelik
_result = [list(someListOfElements) for _ in xrange(x)]
_

これにより、それぞれsomeListOfElementsリストのコピーを持つx個の個別のリストが作成されます(そのリスト内の各項目は参照によるものですが、リストはそのコピーです)。

より理にかなっている場合は、copy.deepcopy(someListOfElements)の使用を検討してください

ジェネレーターとリストの内包表記と物事はかなりPythonicと見なされます。

52
Will

some ソートのループなしで、このようなリストを作成する方法は実際にはありません。ただし、[[]] * xがループを非表示にするように、ループを非表示にする方法は複数あります。式内のループを「隠す」リスト内包表記があります(ビットはありがたいことにまだ明らかです。) two hidden loops([[]] * xのループ)を持つmap(list, [[]]*x)もありますlist()を使用して各リストのコピーを作成するmapの1つ)

また、リストのリストを事前に作成しない可能性もあります。他の答えはすでに簡単なアプローチをカバーしていますが、それがどういうわけかあなたのニーズに合わない場合、他の方法があります。たとえば、必要に応じてresultリストに空のリストを追加する関数を作成し、それを呼び出すことができます。

def append(L, idx, item):
    while len(L) <= idx:
        L.append([])
    L[idx].append(item)

for i in range(x):
    for j in someListOfElements:
        append(result, i, j)

または、リストの代わりにcollections.defaultdict(list)を使用できます:

import collections
result = collections.defaultdict(list)
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)

これには、既存のタイプを使用するメリットがありますが、作業量は少なくなりますが、リストの代わりに(整数でインデックス付けされた)辞書が必要になります。または、リストのように動作するが、IndexErrorを発生させる代わりに、新しいリストをそれ自体に追加するクラスを作成できます。

import UserList
class defaultlist(UserList.UserList):
    def __getitem__(self, idx):
        while len(self) <= idx:
            self.append([])
        return UserList.UserList.__getitem__(self, idx)

result = defaultlist()
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)
7
Thomas Wouters

クイックジェネレーター関数を書くことができます。これには、この特定のケース以外の用途があるので、少し一般化します。これを掘る:

def create(n, constructor=list):
    for _ in xrange(n):
        yield constructor()

次に、リストのリストを作成するには、

result = list(create(10))

空の辞書のリストを作成するには、

result = list(create(20, dict))

(完全を期すため)空のFoosのリストを作成し、

result = list(create(30, Foo))

もちろん、上記のいずれかのタプルを作成することもできます。コンストラクターへの引数を許可するように拡張することも難しくありません。おそらく、インデックスを受け入れ、コンストラクターに渡される引数を返す関数を受け入れるでしょう。

最後に考えたのは、constructorに配置する必要があるのは呼び出し可能なことだけであるため、リストに必要なものを返すものなら何でも渡すことができるということです。たとえば、データベースクエリから結果を引き出すバインドされたメソッド。これは非常に便利な3行のコードです。

5
aaronasterling

リストを適切なループに追加するだけでシンプルに保つのはなぜですか

result = []
for i in range(x):
    result.append([])
    for j in someListOfElements:
        result[i].append(j)

[編集:サンプルの追加]

>>> someListOfElements = ['a', 'b', 'c']
>>> x = 3
>>> result = []
>>> for i in range(x):
...     result.append([])
...     for j in someListOfElements:
...         result[i].append(j)
... 
>>> 
>>> result
[['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c']]
4
pyfunc

runnableサンプルコードを含めてください。そうすれば、自分でコードを実行して、何をしたいかを正確にすぐに確認できます。これが欲しいだけのように見えます:

result = []
for i in range(x):
    data = []
    for j in someListOfElements:
        data.append(j)
    # or data = [j for j in someListOfElements]
    result.append(data)
0
Glenn Maynard