Python中有两个重要的单行习惯用法,可以使这种“简单易懂”。
保证了可迭代对象的从左到右的评估顺序。这使得使用zip(* [iter(s)] * n)将数据系列聚类为n个长度的组成为可能。
因此,适用于您的示例:
>>> num_str = '5,4,2,4,1,0,3,0,5,1,3,3,14,32,3,5'
>>> zip(*[iter(num_str.split(","))]*2)
[('5', '4'), ('2', '4'), ('1', '0'), ('3', '0'), ('5', '1'),
('3', '3'), ('14', '32'), ('3', '5')]
产生每个长度为2的元组。
如果您希望子元素的长度不同:
>>> zip(*[iter(num_str.split(","))]*4)
[('5', '4', '2', '4'), ('1', '0', '3', '0'), ('5', '1', '3', '3'),
('14', '32', '3', '5')]
第二个成语是列表理解。如果您希望子元素成为列表,则可以理解以下内容:
>>> [list(t) for t in zip(*[iter(num_str.split(","))]*4)]
[['5', '4', '2', '4'], ['1', '0', '3', '0'], ['5', '1', '3', '3'],
['14', '32', '3', '5']]
>>> [list(t) for t in zip(*[iter(num_str.split(","))]*2)]
[['5', '4'], ['2', '4'], ['1', '0'], ['3', '0'], ['5', '1'], ['3', '3'],
['14', '32'], ['3', '5']]
zip()将截断所有不完整的子元素组。因此,例如,如果您的字符串不是2的倍数,则将丢失最后一个元素。
如果要返回不完整的子元素(即,如果您num_str
不是子元素长度的倍数),请使用切片成语:
>>> l=num_str.split(',')
>>> [l[i:i+2] for i in range(0,len(l),2)]
[['5', '4'], ['2', '4'], ['1', '0'], ['3', '0'], ['5', '1'],
['3', '3'], ['14', '32'], ['3', '5']]
>>> [l[i:i+7] for i in range(0,len(l),7)]
[['5', '4', '2', '4', '1', '0', '3'], ['0', '5', '1', '3', '3', '14', '32'],
['3', '5']]
如果希望每个元素都是一个int,则可以在此处讨论的其他转换之前应用它:
>>> nums=[int(x) for x in num_str.split(",")]
>>> zip(*[iter(nums)]*2)
# etc etc etc
正如评论中所指出的那样,在Python 2.4+中,您还可以通过将替换为来用生成器表达式替换列表推导:[ ]``( )
>>> nums=(int(x) for x in num_str.split(","))
>>> zip(nums,nums)
[(5, 4), (2, 4), (1, 0), (3, 0), (5, 1), (3, 3), (14, 32), (3, 5)]
# or map(list,zip(nums,nums)) for the list of lists version...
如果您的字符串很长,并且您知道只需要2个元素,则效率更高。