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

时间:2015-04-10 16:10:56

标签: python list python-3.x itertools

我有这个程序我写的是我有两个不相等的列表,其中一个列表中嵌套了其他列表所以我把它弄平了,现在我试图比较两个列表中的值来找到匹配的对然后将它追溯到原始的unflattened列表,但该程序仍然没有产生预期的结果,我希望我以两种不同的方式解决这个问题,但我仍然得到相同的答案这里是我尝试过的远

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是创建的所有对象的列表

2 个答案:

答案 0 :(得分:3)

如果值是不可变的,请使用collections.Counter dict来计算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

根据编辑,您可以针对每个节点检查每个节点,也可以使用dict分组公共节点:

检查每个节点:

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)

使用dict按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选项应该更有效。

答案 1 :(得分:-2)

Try this:

matches = set(List1) & set(List2)