我有一个列表列表,对于列表中的每个列表,我想将它拆分为两个列表,这样每个列表的长度最多为30,否则我会丢弃不能容纳的列表。并且差不多接近30。
例如:列表1的长度为64 - >将它分成两个30,30的列表,并丢弃剩下的4个。
或List 2的长度为41,我生成一个新的30列表并丢弃11.
或列表3的长度为58,我生成两个30和28的列表。
我正在使用我找到的列表拆分功能:https://stackoverflow.com/a/1751478/2027556
现在我的代码是这样的:
new_list = []
for list_ in cluster:
if len(list_) < 31 and len(list_) > 24:
new_list.append(list_)
elif len(list_) >= 31:
chunks_list = chunks(list_, 30)
for item in chunks_list:
if len(item) > 25:
new_list.append(item)
正如你现在所看到的那样我只是制作一个新列表并通过旧列表,但我认为有一个更优雅的pythonic解决方案可能使用列表理解?
答案 0 :(得分:2)
不需要太聪明,你可以使用step
参数range()
:
cluster = list(range(100))
chunk_size = 30
result = [cluster[start:start+chunk_size]
for start in range(0, len(cluster), chunk_size)]
# discard last chunk if too small - adjust the test as needed
if len(result[-1]) < chunk_size:
del result[-1]
result
的值将是列表列表:
[ [0, 1, ..., 29],
[30, 31, ..., 59],
[60, 61, ..., 89] ]
(那说你还没有真正描述输入和输出太清楚 - 即没有给出具体的例子。)
答案 1 :(得分:0)
以下内容应该有效:
tmp = ((x[i:i+30] for i in range(0, len(x), 30)) for x in cluster)
new_list = [x for lst in tmp for x in lst if len(x) > 25]
答案 2 :(得分:0)
new_list = [[lst[i*30:(i+1)*30] for i in xrange(len(lst)/30)] for lst in cluster]
答案 3 :(得分:0)
首先,我使用itertools
docs中的grouper
食谱来获取群组:
new_list = list(grouper(30, cluster))
然后过滤最后一组以删除fillvalue
条目,如果结果不是“大约接近30”,则将其删除。
new_list[-1] = list(filter(None, new_list[-1]))
if len(new_list) < chunk_size:
del result[-1]
如果None
是有效元素,请使用其他内容作为哨兵:
sentinel = object()
new_list = list(grouper(30, cluster, fillvalue=sentinel)
new_list[-1] = [element for element in new_list[-1] if element is not sentinel]
if len(new_list[-1]) < chunk_size:
del result[-1]
与此同时,有一些关于添加zip_strict
到itertools
的讨论,这将允许grouper
食谱返回一个简短的最终组,而不是用fillvalue
填充它。如果这种情况发生在3.4中,你可以将其简化为:
new_list = list(grouper(30, cluster, strict=True))
if len(new_list[-1]) < chunk_size:
del result[-1]
或者,当然,你可以使用python-ideas列表中的一个“严格的分组器”实现,或者只编写你自己的grouper
和filter
个调用上方。
答案 4 :(得分:0)
如果你真的想要列表理解......
new_list = [cluster[i:i+30] for i in xrange(0, len(cluster), 30) if len(cluster[i:i+30]) > 25]
答案 5 :(得分:0)
您可以使用生成器功能以及itertools.islice
:
In [11]: from itertools import islice
In [12]: lis=[range(64),range(41),range(58)]
In [13]: def solve(lis):
for x in lis:
it=iter(x)
q,r=divmod(len(x),30)
if r>25:
for _ in xrange(q+1):
yield list(islice(it,30))
else:
for _ in xrange(q):
yield list(islice(it,30))
....:
In [14]: map(len,list(solve(lis))) #use just `list(solve(lis))` to get the desired answer
Out[14]: [30, 30, 30, 30, 28] # (30,30) from 64, (30) from 41, and (30,28) from 58
答案 6 :(得分:0)
对于两个列表,只需编写2个切片
new_list = [cluster[:30], cluster[30:60]]
答案 7 :(得分:0)
从python itertools修改grouper
,您可以执行以下操作:
def grouper(n, iterable, max_chunks):
args = [iter(iterable)] * n
chunks = []
for zipped in zip_longest(fillvalue=None, *args):
chunks.append([x for x in zipped if x is not None])
if(len(chunks) == max_chunks):
break
return chunks
new_lists = [grouper(10,li,2) for li in list_list]
这将返回一个作为拆分列表的块列表 如果你想要这个更平坦,你可以这样称呼:
new_lists = []
for li in list_list:
new_lists.extend(grouper(10,li,2))