Python 按组连接字符串

Python 按组连接字符串,python,string,group-by,string-concatenation,Python,String,Group By,String Concatenation,我想将一个字符串列表连接到一个列表中的值上分组的新字符串中。以下是我的意思的一个例子: 输入 key = ['1','2','2','3'] data = ['a','b','c','d'] newkey = ['1','2','3'] newdata = ['a','b c','d'] 结果 key = ['1','2','2','3'] data = ['a','b','c','d'] newkey = ['1','2','3'] newdata = ['a','b c','d']

我想将一个字符串列表连接到一个列表中的值上分组的新字符串中。以下是我的意思的一个例子:

输入

key = ['1','2','2','3']
data = ['a','b','c','d']
newkey = ['1','2','3']
newdata = ['a','b c','d']
结果

key = ['1','2','2','3']
data = ['a','b','c','d']
newkey = ['1','2','3']
newdata = ['a','b c','d']
我知道如何连接文本。但是我不知道如何正确地迭代列表中的值来聚合相同键值的公共字符串


感谢您的帮助或建议。谢谢。

您可以在
zip(键,数据)
上使用
itertools.groupby()


使用
itertools.groupby()
函数组合元素;zip允许您将两个输入列表分组为两个输出列表:

import itertools
import operator

newkey, newdata = [], []
for key, items in itertools.groupby(zip(key, data), key=operator.itemgetter(0)):
    # key is the grouped key, items an iterable of key, data pairs
    newkey.append(key)
    newdata.append(' '.join(d for k, d in items))
您可以使用更多的
zip()
magic将其转化为列表理解:

from itertools import groupby
from operator import itemgetter

newkey, newdata = zip(*[(k, ' '.join(d for _, d in it)) for k, it in groupby(zip(key, data), key=itemgetter(0))])
注意,这确实需要对输入进行排序
groupby
仅基于相同的连续键对元素进行分组。另一方面,它确实保留了最初的排序顺序

from collections import defaultdict

d = defaultdict(list)

for k, v in zip(key, data):
    d[k].append(v)

print [(k, ' '.join(v)) for k, v in d.items()]
输出:

[('1', 'a'), ('3', 'd'), ('2', 'b c')]
以及如何获取新列表:

newkey, newvalue = d.keys(), [' '.join(v) for v in d.values()]
和保存的订单:

newkey, newvalue = zip(*[(k, ' '.join(d.pop(k))) for k in key if k in d])

如果你不想导入收藏,你可以使用普通字典

key = ['1','2','2','3']
data = ['a','b','c','d']
newkeydata = {}

for k,d in zip(key,data):
    newkeydata[k] = newkeydata.get(k, []).append(d)

出于多样性的考虑,这里有一个解决方案,它不需要任何外部库,也不需要字典:

def group_vals(keys, vals):
    new_keys= sorted(set(keys))
    zipped_keys = zip(keys, keys[1:]+[''])
    zipped_vals = zip(vals, vals[1:]+[''])
    new_vals = []
    for i, (key1, key2) in enumerate(zipped_keys):
        if key1 == key2:
            new_vals.append(' '.join(zipped_vals[i]))
        else:
            new_vals.append(zipped_vals[i][0])
    return new_keys, new_vals

group_vals([1,2,2,3], ['a','b','c','d'])
# --> ([1, 2, 3], ['a', 'b c', 'd'])

但我知道这很难看,可能没有其他解决方案那么有效。仅用于演示目的。:)

打得好!我真的考虑过了。你如何从你的输出中得到想要的输出呢?这比
groupby
要好,因为它不需要
key
来排序。@defuz:你可以用
zip(*[(k,.join(v))来表示k,v in d.items())
。@MartijnPieters,我还为你保存了订单;)但是为什么?如果内存可用,您也可以使用
newkeydata.setdefault(k,[]).append(d)
,但是defaultdict要干净得多。您在zip(key,data)中缺少k,d:在此之前有此参数: