web-dev-qa-db-ja.com

サブリストの作成

リストのフラット化の反対。

リストと長さnを指定すると、長さnのサブリストのリストが返されます。

def sublist(lst, n):
    sub=[] ; result=[]
    for i in lst:
        sub+=[i]
        if len(sub)==n: result+=[sub] ; sub=[]
    if sub: result+=[sub]
    return result

例:

リストが次の場合:

[1,2,3,4,5,6,7,8]

そしてnは:

3

返品:

[[1, 2, 3], [4, 5, 6], [7, 8]]

もっと雄弁で簡潔な方法はありますか?

余談ですが、リストにリストを追加するときに好ましいことは(上記のコンテキストで):

list1+=[list2]

または:

list1.append(list2)

それを考えると(Summerfeildの 'Programming in Python 3')によると)それらは同じですか?

ありがとう。

18
Michael Puckett

このようなリストのリストは、 リスト内包表記 を使用して作成できます。

_In [17]: seq=[1,2,3,4,5,6,7,8]
In [18]: [seq[i:i+3] for i in range(0,len(seq),3)]
Out[18]: [[1, 2, 3], [4, 5, 6], [7, 8]]
_

ハタのイディオム もあります。

_In [19]: import itertools
In [20]: list(itertools.izip_longest(*[iter(seq)]*3))
Out[20]: [(1, 2, 3), (4, 5, 6), (7, 8, None)]
_

ただし、不足している要素には値Noneが入力されることに注意してください。 izip_longest None以外が必要な場合は、fillvalueパラメータも使用できます。


_list1+=[list2]_-今回は角括弧に注意-はlist1.append(list2)と同等です。コードを書くときの私の最優先事項は、速度ではなく可読性です。このため、list1.append(list2)を使用します。ただし、読みやすさは主観的であり、おそらく慣れ親しんでいる慣用句の影響を大きく受けます。

幸いにも、この場合、読みやすさと速度は一致しているように見えます。

_In [41]: %timeit list1=[1,2,3]; list1.append(list2)
1000000 loops, best of 3: 612 ns per loop

In [42]: %timeit list1=[1,2,3]; list1+=[list2]
1000000 loops, best of 3: 847 ns per loop
_
19
unutbu

以下はどうですか(ここでxはあなたのリストです):

 [x[i:i+3] for i in range(0, len(x), 3)]

これは、n!=3を一般化するのは簡単です。

2番目の質問については、それらは同等なので、スタイルの問題だと思います。ただし、 appendextend を混同していないことを確認してください。

8
NPE

この関数は、あらゆる種類の反復可能(既知の長さのシーケンスだけでなく)を取ることができます。

import itertools

def grouper(n, it):
    "grouper(3, 'ABCDEFG') --> ABC DEF G"
    it = iter(it)
    return iter(lambda: list(itertools.islice(it, n)), [])

print(list(grouper(3, [1,2,3,4,5,6,7,8,9,10])))
# [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
5
tokland

boltons をご存知ですか?

Boltonsは、標準ライブラリと同じ精神を持つ純粋なPythonユーティリティのセットですが、標準ライブラリにはありません。

chunked と呼ばれる、必要なものが組み込まれています

from boltons import iterutils

iterutils.chunked([1,2,3,4,5,6,7,8], 3)

出力:

[[1, 2, 3], [4, 5, 6], [7, 8]]

そしてboltonsのwhatsより魅力的なは、それがchunkediterator、呼び出された chunked_iter なので、全部をメモリに保存する必要はありません。きちんとね?

3
vishes_shell

特定のケースでは、numpyパッケージを使用すると便利な場合があります。このパッケージには reshape ルーチンがあります:

import numpy as np
x = np.array([1,2,3,4,5,6])
np.reshape(x, (-1,3))

ただし、このソリューションは、nの乗算でない場合、リストを埋めません。

1
tsvikas

私はこの分割関数があなたが探しているものを実行すると思います(ただし、リストだけでなく任意のイテレータで機能します)。

from itertools import islice

def take(n, it):
    "Return first n items of the iterable as a list"
    return list(islice(it, n))

def split(it, size):
    it = iter(it)
    size = int(size)
    ret = take(size, it)
    while ret:
        yield ret
        ret = take(size, it)

編集:あなたの言い分については、私はいつもlist.append(blah)を使用しています。

1
Gabriel Grant

私は知っています、それは brainfuck のように見えますが、うまくいきます:

>>> a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
>>> n = 3
>>> [i for j in [[a[t:t+n] for x in a[:1:t+1] if (t%n)==False] for t in range(len(a))] for i in j]
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]

>>> n = 4
>>> [i for j in [[a[t:t+n] for x in a[:1:t+1] if (t%n)==False] for t in range(len(a))] for i in j]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15]]
0
psihodelia