【问题标题】:Save list number within a list only if it contains elements in python仅当列表中包含python中的元素时才将列表编号保存在列表中
【发布时间】:2022-01-03 08:31:38
【问题描述】:

我有一些列表,例如:

my_list_of_list=[['A','B','C','E'],['A','B','C','E','F'],['D','G','A'],['X','Z'],['D','M'],['B','G'],['X','Z']]

如您所见,list 12 共享最多的元素 (4)。因此,仅当 4 个共享元素(ABCE) 存在于该列表中。

然后我在list_shared_number[] 中保存,只有列表 1、2、3 和 6,因为另一个不包含 (A,B,CE)。

预期输出:

print(list_shared_number)
[0,1,2,5]

【问题讨论】:

  • A, B, C or DA, B, C or E?
  • 您的意思是“E”而不是“D”吗?另外,您是指至少一个元素(A 或 B 或 C 或 E)吗?我的最后一个问题是,你想从位置开始(1 是 subfirst 列表)还是索引(0 是第一个 sublist)
  • 请附上你试过的。
  • A、B、C 或 E 对不起,我想要一个 0 索引,你是对的

标签: python python-3.x


【解决方案1】:

可能是次优的,因为我需要对列表进行 3 次迭代,但这是预期的结果:

from itertools import combinations
from functools import reduce

common_elements = [set(i).intersection(j) 
                       for i, j in combinations(my_list_of_list, r=2)]

common_element = reduce(lambda i, j: i if len(i) >= len(j) else j, common_elements)

list_shared_number = [idx for idx, l in enumerate(my_list_of_list)
                          if common_element.intersection(l)]
print(list_shared_number)

# Output
[0, 1, 2, 5]

2 次迭代的替代方案:

common_element = {}
for i, j in combinations(my_list_of_list, r=2):
    c = set(i).intersection(j)
    common_element = c if len(c) > len(common_element) else common_element
list_shared_number = [idx for idx, l in enumerate(my_list_of_list)
                          if common_element.intersection(l)]
print(list_shared_number)

# Output
[0, 1, 2, 5]

【讨论】:

    【解决方案2】:

    您可以使用列表推导式查找共享元素。检查索引 0 和索引 1:

    share = [x for x in my_list_of_list[0] if x in my_list_of_list[1]]
    print(share)
    

    假设j 是每个项目,所以[j for j in x if j in share] 可以找到共享的内部元素。如果这个数组的长度大于 0,那么它应该包含在输出中。

    所以最终的代码是这样的:

    share = [x for x in my_list_of_list[0] if x in my_list_of_list[1]]
    my_list = [i for i, x in enumerate(my_list_of_list) if len([j for j in x if j in share]) > 0]
    print(my_list)
    

    【讨论】:

    • 如果你随机播放列表,它不起作用。您需要使用所有可能的组合来找到最长的公共集。
    • 为什么?问题是share 变量?我从共享元素应该从 my_list_of_list[0] 和 my_list_of_list[1] 中提取的问题中得到。是真的吗?
    • 不幸的是,我认为这只是一个例子。 OP 希望首先在整个列表中找到最长的公共集。
    • 应该在问题中澄清。我尝试在我的回答中包含您的评论。谢谢。
    【解决方案3】:

    您可以使用itertools.combinations 和设置操作。

    在第一行中,您可以找到列表对中最长的交集。在第二行中,您遍历 my_list_of_list 以识别包含您在第一行中找到的集合中的元素的列表。

    from itertools import combinations
    comparison = max(map(lambda x: (len(set(x[0]).intersection(x[1])), set(x[0]).intersection(x[1])), combinations(my_list_of_list, 2)))[1]
    out = [i for i, lst in enumerate(my_list_of_list) if comparison - set(lst) != comparison]
    

    输出:

    [0, 1, 2, 5]
    

    【讨论】:

    • max 在这里不起作用。如果您将列表 my_list_of_list[::-1] 反转,则输出将为 [3, 6]
    • 为什么是permutations 而不是combinations
    • @Corralien 我不太了解。对于my_list_of_list[::-1],它没有给我[3,6]
    • @Corralien 对,这里应该是组合,因为我们在这里进行选择。谢谢。
    • 试试:import random; random.shuffle(my_list_of_list),你就会明白了。
    【解决方案4】:

    哦,天哪,所以我的有点乱,但是我没有使用任何导入,并且我包括了两个最相似的列表的初始“发现”。这可以很容易地进行优化,但它确实可以满足您的需求。

    my_list_of_list=[['A','B','C','E'],['A','B','C','E','F'],['D','G','A'],['X','Z'],['D','M'],['B','G'],['X','Z']]
    my_list_of_list = list(map(set,my_list_of_list))
    mostIntersects = [0, (None,)]
    
    for i, IndSet in enumerate(my_list_of_list):
        for j in range(i+1,len(my_list_of_list)):
            intersects = len(IndSet.intersection(my_list_of_list[j]))
            if intersects > mostIntersects[0]: mostIntersects = [intersects, (i,j)]
    FinalIntersection = set(my_list_of_list[mostIntersects[1][0]]).intersection(my_list_of_list[mostIntersects[1][1]])
    
    skipIndexes = set(mostIntersects[1])
    for i,sub_list in enumerate(my_list_of_list): 
        [skipIndexes.add(i) for char in sub_list 
            if i not in skipIndexes and char in FinalIntersection]
    
    print(*map(list,(mostIntersects, FinalIntersection, skipIndexes)), sep = '\n')
    

    印刷品提供了这一点:

    [4, (0, 1)]
    ['E', 'C', 'B', 'A']
    [0, 1, 2, 5]
    

    首先使用 map 函数将列表转换为集合(必须将其转回列表,以便我可以使用 len 并正确迭代)然后将每个列表与列表列表中的其他列表相交并计数每个中有多少元素。每次我找到一个更大的数字时,我将 mostIntersections 设置为等于 len 和设置的索引。一旦我完成了所有这些,我得到两个索引处的列表(在本例中为 0 和 1)并将它们相交以给出元素列表 [A,B,C,E] (var:finalIntersection)。从那里,我只是遍历所有尚未使用的列表,并检查是否在 finalIntersection 中找到了任何元素。如果是,则将列表的索引附加到skipIndexes。这导致索引的最终列表 {indices? idk} 你所追求的。从技术上讲,结果是一个集合,但要将其转换回来,您只需使用 list({0,1,2,5}) 即可获得您所追求的值。

    【讨论】:

      猜你喜欢
      • 2015-12-06
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多