如何简化这些代码?(如果两个嵌套列表中的前几个元素相同,则为count + 1)

时间:2018-09-18 15:16:28

标签: python

我有两个嵌套列表:

A=[[a,1,A],[a,2,A],[a,1,A],[b,1,B],[a,1,A]]

B=[[a,1,A],[a,2,A],[b,1,B]]

我要计算的是A中等于B(B就像一个索引)的元素,然后追加B

最后我们需要得到

C=[[[a,1,A,3],[a,2,A,1],[b,1,B,1]]]

最后一个元素是A和B中相同内容的计数

我的代码:

for i in range(len(index)):
    index[i].append(0)
    for j in range(len(df)):
        if index[i][0]==df[j][0] and index[i][1]==df[j][1] and index[i][2]==df[j][2]:
            index[i][3]+=1
return

但是当A[i]中有很多元素(我们不能使用过多的and)时,这似乎很少见

我们如何使编写更容易?

3 个答案:

答案 0 :(得分:3)

您不需要比较列表中的每一项,可以在整个列表中使用==:

for i in range(len(index)):
    counter = 0
    for j in range(len(df)):
        if index[i] == df[j]:
            counter += 1
    index[i].append(counter)

答案 1 :(得分:1)

您可以在此处使用collections.Counter作为O(n)解决方案:

from collections import Counter
cnt = Counter(map(tuple, A))
print(cnt)
#Counter({('a', 1, 'A'): 3, ('a', 2, 'A'): 1, ('b', 1, 'B'): 1})

我将A中的值映射到tuple,因为您需要Counter的可哈希类型。

现在您有了计数,只需查找并为B中的每个值附加计数:

C = [b + [cnt.get(tuple(b), 0)] for b in B]
print(C)
#[['a', 1, 'A', 3], ['a', 2, 'A', 1], ['b', 1, 'B', 1]]

在幕后,collections.Counter正在大致执行以下操作:

cnt = {}
for a in (tuple(a) for a in A):
    if a not in cnt:
        cnt[a] = 0
    cnt[a] += 1

如您所见,只有一个通过列表A,您就拥有A中所有值的计数。通过提前预先计算计数,您可以在恒定时间B中进行后续查找(O(1)中的值)。

将此与其他形式的解决方案进行对比:

for b in B:
    for a in A:
        if a == b:
            # increment a counter

这些效率低下,因为您正在为A中的每个值遍历B中的所有值。如果这些列表的长度很小,您将不会注意到差异,但是随着数据量的增长,差异将会很大。

答案 2 :(得分:1)

有一个内置的.count方法对此很有效

c = []

for item in (b):
    num = a.count(b) 
    item.append(num)
    c.append(item)

print(c)
(xenial)vash@localhost:~/python/stack_overflow$ python3.7 nest_list.py
[['a', 1, 'A', 0], ['a', 2, 'A', 0], ['b', 1, 'B', 0]]