Python 2.7:高效重新格式化元组列表

时间:2016-02-14 22:15:44

标签: python string list

我想重新格式化以下列表,其中包含带有整数(在某些元组之间共享)和字符串(对每个元组特殊)的元组

mylist = [(8, 'dddd'), (8, '33333'), (8, 'fdsss'), (9, 'fsfjs'),(10, 'dddd'), (10, '33333'), (12, 'fdsss'), (12, 'fsfjs')]

这样每个元组都包含一个整数和一个属于它的所有字符串的串联字符串,如下所示:

mynewlist = [(8, 'dddd, 33333, fdsss'), (9, 'fsfjs'),(10, 'dddd, 333333'), (12, 'fdsss, fsfjs')

经过一番考虑之后,我提出的最简约的解决方案是简单地遍历所有元组并连接字符串,直到整数与下一个不匹配:

mynewlist = []
label = ''
for i in range(len(mylist)-1):
    if mylist[i][0] != mylist[i+1][0]:
        mynewlist.append(tuple([mylist[i][0], label + mylist[i][1]]))
        label = ''
    else:
        label = label + mylist[i][1] + ','

这很好用。但是,我想知道是否有更高效/ Pythonic的方式来生成列表。我考虑使用列表理解,但这不允许我选择字符串而不经过整个列表多次;需要为每个唯一的整数运行列表推导,这看起来很浪费。我还考虑通过索引预先选择与唯一整数相关联的字符串,但这对我来说似乎是非Pythonic。

建议非常感谢。谢谢!

3 个答案:

答案 0 :(得分:6)

您可以使用itertools.groupby()在此处进行分组:

from itertools import groupby
from operator import itemgetter

mynewlist = [
    (key, ', '.join([s for num, s in group]))
    for key, group in groupby(mylist, itemgetter(0))]

这使用list comprehensions处理每个组并从分组的元组中提取字符串以进行连接。 operator.itemgetter() object告诉groupby()将输入分组到第一个元素:

>>> from itertools import groupby
>>> from operator import itemgetter
>>> mylist = [(8, 'dddd'), (8, '33333'), (8, 'fdsss'), (9, 'fsfjs'),(10, 'dddd'), (10, '33333'), (12, 'fdsss'), (12, 'fsfjs')]
>>> [(key, ', '.join([s for num, s in group])) for key, group in groupby(mylist, itemgetter(0))]
[(8, 'dddd, 33333, fdsss'), (9, 'fsfjs'), (10, 'dddd, 33333'), (12, 'fdsss, fsfjs')]

请注意,groupby()迭代器仅匹配连续匹配元素。这意味着如果您的输入未排序,则具有相同初始元素的元组不一定总是被放在一起。如果您的输入未排序,并且您需要将具有相同起始元素的所有元组分组,而不管它们在输入序列中的位置,请使用字典首先对元素进行分组:

grouped = {}
for key, string in mylist:
    grouped.setdefault(key, []).append(string)
mynewlist = [(key, ', '.join([s for num, s in group])) for key, group in grouped.items()]

答案 1 :(得分:2)

defaultdict可以解决问题:

from collections import defaultdict
dct = defaultdict(list)
for k, v in mylist:
    dct[k].append(v)
mynewlist = [(k, ','.join(v)) for k, v in dct.iteritems()]

答案 2 :(得分:-1)

您可以使用自定义Object {0: "Netherlands Antilles", 49518: "Rwanda", 51537: "Somalia", 69543: "Yemen", 99237: "Iraq", 102358: "Saudi Arabia", 130758: "Iran", 146669: "Cyprus", 149590: "Tanzania", 163843: "Syria", 174982: "Armenia", 192950: "Kenya", 203312:... 子类:

来执行此操作
dict

现在class mydict(dict): def __setitem__(self, key, val): self.setdefault(key,[]).append(val) >>> mylist = [(8, 'dddd'), (8, '33333'), (8, 'fdsss'), ... (9, 'fsfjs'),(10, 'dddd'), (10, '33333'), ... (12, 'fdsss'), (12, 'fsfjs')] >>> d = mydict() >>> for key, val in mylist: ... d[key] = val 包含类似

的内容
d

(按项目顺序排列),您可以轻松地将其按到您想要的形式:

{8: ['dddd', '33333', 'fdsss'], 9: ['fsfjs'], 10: ['dddd', '33333'], 12: ['fdsss', 'fsfjs']}