如何比较两个不相等的列表并将匹配元素值追加回第一个列表

How to compare two unequal lists and append matching elements value back to the first List

我正在编写这个程序,其中有两个不相等的列表,其中一个列表中嵌套了其他列表,所以我将其展平,现在我正在尝试比较两个列表中的值以找到匹配对,然后将其追加到原始的未展平列表中,但程序仍无法产生我想要的预期结果我已经用两种不同的方式解决了这个问题,但我仍然得到了相同的答案这就是我所拥有的目前已尝试

List1  = [['A'],['b']]
List2 = ['a','A','c','A','b','b','A','b' ]

flattened = list(itertools.chain(*List1))

''' a counter i created to keep List1 going out of range and crashing
the program
'''
coun = len(flattened)
coun-=1
x = 0

for idx, i in enumerate(List2):
    if i in flattened:
        List1[x].append(List2[idx])
        if x < coun:
            x +=1

print(List1)

这是我尝试使用 itertools 压缩两个不相等列表的第二种方法

import itertools

List1  = [['A'],['b']]
List2 = ['a','A','c','A','b','b','A','b' ]

flattened = list(itertools.chain(*List1))

''' a counter i created to keep List1 going out of range and crashing
the program
'''
coun = len(flattened)
coun-=1
x = 0

for idx,zipped in enumerate(itertools.zip_longest(flattened,List2)):
    result = filter(None, zipped)
    for i in result:
        if flattened[x] == List2[idx]:
            List1[x].append(List2[idx])
            if x < coun:
                x +=1

print(List1)

两个程序都产生输出

[['A', 'A'], ['b', 'A', 'b', 'b', 'A', 'b']]

但我正在努力达到

[['A', 'A', 'A', 'A'], ['b', 'b', 'b', 'b']]

我什至不知道我是否以正确的方式处理这个问题,但我知道问题出在扁平化列表与 List2 的长度不同,但我似乎找不到任何解决方法它...顺便说一句,我在 Python 中还是个新手,所以请尝试解释您的答案,以便我向您学习。谢谢

编辑:这就是我使用用户输入的值获取和设置对象属性的方式,认为它现在缺少类型检查但可以稍后添加

class criticalPath:

    def __init__(self):
        '''
        Initialize all the variables we're going to use to calculate the critical path
        '''
        self.id = None
        self.pred = tuple()
        self.dur = None
        self.est = None
        self.lst = None
        #list to store all the objects
        self.all_objects = list()

    def create_objects(self):

        return criticalPath()

    def get_properties(self):
        ''' 
        This functions gets all the input from the user and stores the
        activity name a string, the predecessor in a tuple and the duration
        in a string
        '''
        r = criticalPath()
        Object_list = list()
        num_act = int(input('How many activities are in the project:\n'))
        for i in range(num_act):
            name = input('what is the name of the activity {}:\n'.format(i+1))
            activity_object = r.create_objects()
            pred = input('what is the predecessor(s) of the activity:\n')
            pred = tuple(pred.replace(',', ''))
            dur = input('what is the duration of the activity:\n')

            #sets the properties of the objects from what was gotten from the user
            activity_object.set_properties(name, pred, dur)
            #****
            Object_list.append(activity_object)

            self.all_objects.append(activity_object)



        return Object_list

    def set_properties(self, name, predecessor, duration):
        self.id = name
        self.pred = predecessor
        self.dur = duration

所以all_objects和Object_list是创建的所有对象的列表

如果您的值是不可变的,请使用 collections.Counter 字典来计算 List2 中元素的出现次数并添加出现次数 * :

List1  = [['A'],['b']]
List2 = ['a','A','c','A','b','b','A','b' ]

from collections import Counter

# gets the frequency count of each element in List2
c = Counter(List2)

# create frequency + 1 objects using the value from our Counter dict
# which is how many times it appears in List2
print([sub * (c[sub[0]] + 1) for sub in List1])
[['A', 'A', 'A', 'A'], ['b', 'b', 'b', 'b']]

您可以使用 [:]:

更改原始对象
List1[:] = [sub * c[sub[0]]+sub for sub in List1]

要使用枚举和更新 List1 来做到这一点:

from collections import Counter

c = Counter(List2)

from copy import deepcopy

# iterate over a copy of List1
for ind, ele in enumerate(deepcopy(List1)):
    # iterate over the sub elements
    for sub_ele in ele:
        # keep original object and add objects * frequency new objects
        List1[ind].extend([sub_ele] * c[sub_ele])

print(List1)

如果您有可变值,您将需要根据它们的创建方式在生成器表达式中制作副本或创建新对象:

from copy import deepcopy
for ind, ele in enumerate(deepcopy(List1)):
    for sub_ele in ele:
        List1[ind].extend(deepcopy(sub_ele) for _ in range(c[sub_ele]))

print(List1)

无需检查对象,因为不在 List2 中的对象的值为 0,因此 0 * object == no object added

根据编辑,您可以针对每个节点检查每个节点或使用字典对公共节点进行分组:

检查每个节点:

from copy import deepcopy

for ind, st_nodes in enumerate(starting_nodes):
    for node in object_list:
        if st_nodes[0].id == node.pred:
            starting_nodes[ind].append(deepcopy(node))
print(starting_nodes)

使用字典根据 pred 属性对所有节点进行分组:

from copy import deepcopy
from collections import defaultdict

nodes = defaultdict(list)
for node in object_list:
    nodes[node.pred].append(node)

for ind, st_nodes in enumerate(starting_nodes):
    starting_nodes[ind].extend(deepcopy(nodes.get(st_nodes[0].id,[])))

对于更大的输入,dict 选项应该更有效。

试试这个:

matches = set(List1) & set(List2)