遍历包含数组数据的2个列表

5

这个问题让我头疼,我很难通过for循环找到解决方案。

基本上,我的数据长这样:

short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list  = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13] ]

我需要知道短列表(short_list)中每一行中的数字在长列表(long_list)的每一行中出现的次数,当两个列表索引相同时,不需要进行比较,因为它们来自同一数据集。
例如: 我需要知道长列表中[2, 3, 4, 5, 6]、[6, 7, 8, 9, 10]和[9, 10, 11, 12, 13]三行中数字[1, 2, 3]的出现次数,然后继续处理short_list中的下一行数据。

我无法理解这部分内容,当两个列表索引来自同一数据集时,它们相同时不需要进行比较。 提供一个示例来说明这种情况。 - Shiva Kishore
1
给定的例子的正确答案是什么? - kszl
@ElFred:期望的输出是什么? - mhawke
@ElFred,以下回答有没有帮助?如果有,请随意接受其中一个(左边的勾)以便其他用户可以看到已接受的解决方案。 - jpp
谢谢提醒。我选择了最易懂的一个。 - El Fred
显示剩余2条评论
5个回答

3

这是一种方法,纯属我脑海中的想法,可能还有更好的方式。

from collections import defaultdict

short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list  = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13] ]

occurrences = defaultdict(int)

for i, sl in enumerate(short_list):
    for j, ll in enumerate(long_list):
        if i != j:
            for n in sl:
                occurrences[n] += ll.count(n)

>>> occurrences
defaultdict(<class 'int'>, {1: 0, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 0, 8: 0, 9: 1, 10: 1, 11: 0, 12: 0})

请注意,enumerate()用于在迭代时提供索引。这些索引被比较以确保不会比较相同相对位置的子列表。
结果是一个字典,其键为短列表中的项目,值为长列表中具有相同索引的子列表不包括其中的该项目的总计数。

这将会得到预期的结果! - El Fred

2
这是一种暴力解决方案。我修改了输入数据,以使结果更有趣:
from collections import Counter
from toolz import concat

short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list  = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [2, 3, 11, 12, 13] ]

for idx, i in enumerate(short_list):
    long_list_filtered = (x for x in concat(long_list[:idx] + long_list[idx+1:]) if x in set(i)))
    print(idx, Counter(long_list_filtered))

# 0 Counter({2: 2, 3: 2})
# 1 Counter({4: 1, 5: 1, 6: 1})
# 2 Counter()
# 3 Counter({10: 1})

2

可能的方法:

  • 循环遍历short_list中的每个列表。
  • long_list中与当前列表不同索引的每个列表展平,并将其转换为集合。
  • 创建一个collections.Counter()来存储短列表中出现在展平列表中的每个元素的计数。

演示:

from collections import Counter
from itertools import chain

short_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
long_list  = [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13]]

for i, short_lst in enumerate(short_list):
    to_check = set(chain.from_iterable(long_list[:i] + long_list[i+1:]))
    print(Counter(x for x in short_lst if x in to_check))

输出:

Counter({2: 1, 3: 1})
Counter({4: 1, 5: 1, 6: 1})
Counter({9: 1})
Counter({10: 1})

1
for L1 in short_list:
  for L2 in long_list:
    if not set(L1).issubset(set(L2)):
      for x in L1:
        print("{} has {} occurrences in {}".format(x, L2.count(x), L2))

虽然这段代码片段可能解决了问题,但是附上解释真的有助于提高你的帖子质量。记住,你是在回答未来读者的问题,而这些人可能不知道你提供代码建议的原因。 - Isma
我实际上选择了这个作为我的首选解决方案,因为它易于理解,而且很简短。其他给出的解决方案也是有效的,但这个由于简单性而获得了额外的分数。谢谢! - El Fred

0
short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list  = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13] ]
occ = []
for si in short_list:
    occi = []
    for i, e in enumerate(si):
        count = 0
        for li in long_list:
            for j, e1 in enumerate(li):
                if i == j:
                    continue
                elif e == e1:
                    count += 1
        occi.append(count)
    occ.append(occi)
print occ

应该可以运行, 愉快编程 :)


它没有给出预期的结果。结果只对第一行正确。这应该是预期的结果:[[0,1,1],[1,1,1],[0,0,1],[1,0,0]] - El Fred

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接