按后缀组合列表元素

时间:2017-10-19 20:36:13

标签: python list

给出两个带后缀的列表:

l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']

我想将它们组合起来:

['C_1', 'C_2', 'B_1', 'B_2', 'A', 'D']

要将元素与l1组合作为锚点。这意味着,如果C_*位于B_*中的l1之前,则输出中将保留相同的顺序。此外,具有相同前缀C_*的元素将按后缀的递增顺序组合在一起。带有后缀的元素按照它们出现的顺序放置,如上所示。

您可以假设l1中的所有元素都有后缀_1l2中的所有元素都有后缀_2

我试过这个:

from collections import OrderedDict
from itertools import chain

o = OrderedDict()
for x in l1 + l2:
    o.setdefault(x.split('_')[0], []).append(x) 

result = list(chain.from_iterable(o.values()))

哪个有效,但想知道是否有更简洁的方法可以做到这一点。

编辑:

后缀只是该元素出现在哪个列表中的一个代表。假设我C_1来自l1C_2来自l2,然后是{{1 }}元素基于C_*中的l1以及最终列表中的l2显示(因此,它是... C_1, C_2...)。

此外,l1l2中的所有元素都是彼此独一无二的。希望有所帮助。

4 个答案:

答案 0 :(得分:3)

Alex answer很短,但使用的list.index复杂度为O(n)

我建议使用构建p作为字典进行小修改,反转迭代以模拟index的工作方式(否则当出现多于1次时返回最后的索引)。

在这种情况下,排序键函数使用dict查找,而不是更快:

l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']

p = {s[0]:i for i,s in reversed(list(enumerate(l1 + l2)))}
print(sorted(l1 + l2, key=lambda x: (p[x[0]], x)))

答案 1 :(得分:1)

使用itertools.groupby()sorted()函数:

import itertools

l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']
l1_len = len(l1)
groups_gen = (list(g) for k,g in itertools.groupby(sorted(l1+l2), key=lambda x: x[0] or '_' not in x))
result = list(itertools.chain.from_iterable(sorted(groups_gen,
              key=lambda x: l1.index(x[0]) if x[0] in l1 else l1_len)))

print(result)

输出:

['C_1', 'C_2', 'B_1', 'B_2', 'A', 'D']

答案 2 :(得分:1)

按照l1中前缀出现的索引对所有元素进行排序,使用字符串的其余部分来打破关系:

p = [s[0] for s in l1 + l2]
print(sorted(l1 + l2, key=lambda x: (p.index(x[0]), x)))

p使用l1l2的前缀,以便p.index(x[0])不会引发错误。

答案 3 :(得分:0)

您可以通过此方法完成

l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']

首先选择所有第一个常用词项

new=[y for item in l1 for item2 in l2 for y in  [item] + [item2] if item[0]==item2[0]]

注意我在上面的列表理解中使用了extend。

现在只需查找除第一个字母的常用项目之外剩余的项目:

    for item1 in l2:
        for item2 in l1:
            if item1 not in new:
                new.append(item1)

            elif item2 not in new:
                new.append(item2)


print(new)