kjo*_*kjo 12 python python-itertools map-function
在Python中,如果n是k(IOW,)的倍数,很容易将n长列表分解为k -size块.这是我最喜欢的方法(直接来自文档):n % k == 0
>>> k = 3
>>> n = 5 * k
>>> x = range(k * 5)
>>> zip(*[iter(x)] * k)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
Run Code Online (Sandbox Code Playgroud)
(诀窍是[iter(x)] * k产生一个对同一个迭代器的k个引用列表,如返回的那样.然后通过调用迭代器的每个k副本一次来生成每个块.之前是必要的因为期望接收它的参数为"单独的" "迭代器,而不是它们的列表."iter(x)zip*[iter(x)] * kzip
我用这个习语看到的主要缺点是,当n不是k的倍数(IOW,n % k > 0)时,剩下的条目就被省略了; 例如:
>>> zip(*[iter(x)] * (k + 1))
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)]
Run Code Online (Sandbox Code Playgroud)
还有一个替代习语,其输入稍长一些,产生的结果与上面的结果相同n % k == 0,并且在以下情况下具有更可接受的行为n % k > 0:
>>> map(None, *[iter(x)] * k)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
>>> map(None, *[iter(x)] * (k + 1))
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, None)]
Run Code Online (Sandbox Code Playgroud)
至少,这里保留了剩余的条目,但最后一个块被填充None.如果只需要填充的不同值,则itertools.izip_longest解决问题.
但是假设所需的解决方案是最后一个块未填充的解决方案,即
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14)]
Run Code Online (Sandbox Code Playgroud)
是否有一种简单的方法来修改map(None, *[iter(x)]*k)成语来产生这个结果?
(当然,通过编写一个函数来解决这个问题并不困难(例如,参见如何将列表拆分成均匀大小的块的许多精细回复?或者什么是最"迭代"迭代的方法)列表块?).因此,对于这一问题作出更准确的标题是"如何拯救map(None, *[iter(x)]*k)成语?",但我认为这将挡板很多读者.)
令人震惊的是,将列表分成均匀大小的块是多么容易,并且即使这两个问题似乎具有相似的复杂性,也很难(相比之下)摆脱不必要的填充.