我有两个嵌套列表:
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
)时,这似乎很少见
我们如何使编写更容易?
答案 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]]