给出一个列表[2,8,13,15,24,30],其中所有元素都应该在范围内(31)。现在我想把它分成3个列表,第一个列表的数字从0到10,第二个列表的数字从11到20,其他的到其余的。
这是我丑陋的代码:
numbers = [2,8,13,15,24,30]
mylist = [[],[],[]] # I hate this the most...
for i in numbers:
if i <= 10 :
mylist[0].append(i)
elif i > 10 and i <= 20:
mylist[1].append(i)
else:
mylist[2].append(i)
print mylist
我认为这不是一个很好的方法。有什么建议吗?
答案 0 :(得分:3)
由于您的输入已排序,您可以使用itertools.groupby
一次性完成此操作:
from itertools import groupby
[list(g) for _,g in groupby(numbers, lambda x: x//10)]
Out[3]: [[2, 8], [13, 15], [24, 26]]
无需以这种方式初始化一堆列表,groupby
可以即时生成它们。
就你想要如何处理模10边界而言,这可能是一个接一个的;如果不清楚你总是可以定义自己的grouper
函数:
def grouper(x):
'''bins matching the semantics:
[0,10] (10,20] (20, 30]'''
return (x-1)//10 if x > 0 else 0
并因此使用它:
numbers = [2,8,13,15,24,30]
[list(g) for _,g in groupby(numbers, grouper)]
Out[5]: [[2, 8], [13, 15], [24, 30]]
答案 1 :(得分:1)
如果不重新考虑您的基本方法,您可以:
for n in numbers:
mylist[n//10].append(n)
这利用整数除法,例如19//10
= 1。
使用其他Python构造有更多优雅的方法可以做到这一点;我会为那些人做出第二个答案。但是现在,这是一种快速,简单且不太令人作呕的方式来做你想做的事。
答案 2 :(得分:1)
def filterList(original, lower, upper):
return filter(lambda i : i > lower and i <= upper, original)
这可以像这样调用
firstSlice = filterList(numbers, 0, 10)
>>> firstSlice
[2, 8]
制作你的范围列表
ranges = [0, 10, 20, 30]
然后在列表理解中制作2D列表
>>> [filterList(numbers, ranges[i], ranges[i+1]) for i in range(len(ranges)-1)]
[[2, 8], [13, 15], [24, 26]]
答案 3 :(得分:1)
如何使用reduce
?
numbers = [2,8,13,15,24,26]
def part(acc, x):
# first list with numbers from 0 to 10,
# the second one with numbers from 11 to 20,
# and the others into the rest.
#
# This is *not* the same as:
# acc[x/10].append(x)
#
if x < 10:
acc[0].append(x)
elif x > 20:
acc[2].append(x)
else:
acc[1].append(x)
return acc
print reduce(part, numbers, [[],[],[]])
要删除讨厌的[[],[],[]]
,如果你可以使用字典而不是列表:
from collections import defaultdict
numbers = [2,8,13,15,24,26]
def part(acc, x):
if x < 10:
acc[0].append(x)
elif x > 20:
acc[2].append(x)
else:
acc[1].append(x)
return acc
print reduce(part, numbers, defaultdict(list))
产:
defaultdict(<type 'list'>, {0: [2, 8], 1: [13, 15], 2: [24, 26]})
答案 4 :(得分:1)
一种更好的方法是使用默认的dicts:
from collections import defaultdict
output = defaultdict(list)
for n in numbers:
output[n//10].append(n)
这会创建一个带有默认元素的dict(如果访问尚未创建的键),则为空列表。您不需要在原始代码示例中创建您不喜欢的空列表列表。
然后您可以按十年访问输出,即output
是dict时,output[0]
是一个列表。
如果您需要保留原始输出逻辑,将此dict转换为列表列表很简单。
答案 5 :(得分:0)
不确定优雅的重要性,但列表推导应该有效:
numbers = [2,8,13,15,24,26]
mylist = []
mylist.append([x for x in numbers if x <=10])
mylist.append([x for x in numbers if x > 10 and x <= 20])
mylist.append([x for x in numbers if x > 2 ])
print mylist