是否有“简单”的方法将包含数字的str转换为[x,y] int列表?
# from: '5,4,2,4,1,0,3,0,5,1,3,3,14,32,3,5' # to: [[5, 4], [2, 4], [1, 0], [3, 0], [5, 1], [3, 3], [14, 32], [3, 5]]
顺便说一下,下面的方法可以工作,但是并不能简单明了。。。此外,可以假定输入str已经过验证,以确保它仅包含偶数个逗号分隔的数字。
num_str = '5,4,2,4,1,0,3,0,5,1,3,3,14,32,3,5' numpairs_lst = [] # ends up as [[5, 4], [2, 4], [1, 0], ...] current_num_str = '' # the current num within the str; stop when a comma is found xy_pair = [] # this is one of the [x,y] pairs -> [5, 4] for ix,c in enumerate(num_str): if c == ',': xy_pair.append(int(current_num_str)) current_num_str = '' if len(xy_pair) == 2: numpairs_lst.append(xy_pair) xy_pair = [] else: current_num_str += c # and, take care of last number... xy_pair.append(int(current_num_str)) numpairs_lst.append(xy_pair)
Python中有两个重要的单行习惯用法,可以使这种“简单易懂”。
第一个习惯用法是使用zip()。从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不是子元素长度的倍数),请使用切片成语:
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个元素,则效率更高。