我有一个列表列表,如何提取具有公共值的子列表索引?

时间:2019-07-02 13:30:47

标签: python

我想要以下具有重叠元素的列表中的项目的索引。

slist = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4], [7, 8, 9, 10]]

输出应类似于:

[0,1,2] and [3]

我尝试了以下方法,但是它给了我成对的值,很难像我期望的那样将值分开

    for ((i,a),(j,b)) in itertools.combinations(enumerate(slist),2):
        if len(a.intersection(b)) > 0:
            print("overlapping",i,j)
        else:
            print("non overlapping",i,j)
Output:
('non overlapping', 0, 1)
('non overlapping', 0, 2)
('overlapping', 0, 3)
('overlapping', 1, 2)
('non overlapping', 1, 3)
('non overlapping', 2, 3)

2 个答案:

答案 0 :(得分:4)

您可以使用列表理解来做到这一点:

>>> slist = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4], [7, 8, 9, 10]]
>>> sets = tuple(map(set, slist))
>>> list(map(list, {tuple(i for i, _s in enumerate(sets) if s & _s) for s in sets}))
[[0, 1, 2], [3]]

如果它使可读性更强/更易于理解,我只是在使用map将元组再次放入列表中。您需要使用元组,因为列表和集合不可散列。如果您不映射列表,则它更易读,但会生成一个元组列表。

list({tuple(i for i, _s in enumerate(sets) if s & _s) for s in sets}))

答案 1 :(得分:1)

您可以尝试以下操作:

  • 创建字典,为每个子列表保留潜在的其他重叠列表
  • 定义两个列表之间的重叠函数。您可以在两个intersection之间使用set
  • 然后针对每个子列表组合,查看它们是否重叠。如果它们,则保存彼此的索引。要找到组合,我使用itertools.combinations,如问题中所示。
  • 最后,要获得预期的输出,您需要从字典中删除重复项。

代码在这里:

import itertools

slist = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4], [7, 8, 9, 10]]

# Dictionnary to keep overlapping index
dict_ = {i: [i] for i in range(len(slist))}


# Iterate all combination
for combo in itertools.combinations([i for i in range(len(slist))], 2):
    sublist_1 = slist[combo[0]]
    sublist_2 = slist[combo[1]]
    # Check if they overlap
    if len(set(sublist_1).intersection(set(sublist_2))) > 0:
        # Save index
        dict_[combo[0]].append(combo[1])
        dict_[combo[1]].append(combo[0])

print(dict_)
# {0: [0, 1, 2], 1: [1, 0, 2], 2: [2, 0, 1], 3: [3]}

# Order each sublist in list of index to then remove duplicates
list_ = [set(sub) for sub in (list(dict_.values()))]

print([list(i) for i in set(map(tuple, list_))])
# [[0, 1, 2], [3]]