【问题标题】:In Python, how can I get the intersection of two lists, preserving the order of the intersection?在 Python 中,如何获取两个列表的交集,同时保留交集的顺序?
【发布时间】:2013-05-16 16:34:44
【问题描述】:

我有一个列表列表(“子列表”),我想查看是否有任何未指定长度的相同 序列 出现在多个子列表中。为了澄清,必须保留项目的顺序 - 我不希望每个子列表的交集作为一个集合。必须至少有 2 个按顺序匹配的项目。 请看下面的例子。

输入:

someList = [[0,1,3,4,3,7,2],[2,3,4,3],[0,3,4,3,7,3]]

期望的输出:(将被打印到文件但不要担心这个细节)

sublist0_sublist1 = [3,4,3]#第一个和第二个子列表的交集

sublist0_sublist2 = [3,4,3,7]#第一个和第三个子列表的交集

sublist1_sublist2 = [3,4,3]#第二个和第三个子列表的交集

【问题讨论】:

  • 结果中的项目必须在输入列表中连续出现吗?
  • 然后查找“最长公共子串”算法,假设当有多个子串时您想要最长的此类子串。 @Colleen 的链接似乎不相关。
  • 啊,没有意识到另一个问题是 1. 比标题说的更严格,2. 不需要连续的子序列。在这种情况下,请查看 stackoverflow.com/questions/14032903/… 以获取算法帮助,尽管它使用的是 c++ 而不是 python。
  • 也许您可以将它们组合成由逗号等符号分隔的字符串。匹配 "1,34" 和 [1,34] 应该返回相同的结果。

标签: python sequence intersection preserve


【解决方案1】:

为您整理了这个(包括您的评论,即应在列表中返回等长的最大子列表):

def sublists(list1, list2):
    subs = []
    for i in range(len(list1)-1):
        for j in range(len(list2)-1):
            if list1[i]==list2[j] and list1[i+1]==list2[j+1]:
                m = i+2
                n = j+2
                while m<len(list1) and n<len(list2) and list1[m]==list2[n]:
                    m += 1
                    n += 1
                subs.append(list1[i:m])
    return subs

def max_sublists(list1, list2):
    subls = sublists(list1, list2)
    if len(subls)==0:
        return []
    else:
        max_len = max(len(subl) for subl in subls)
        return [subl for subl in subls if len(subl)==max_len]

这适用于这些情况:

In [10]: max_sublists([0,1,3,4,3,7,2],[0,3,4,3,7,3])
Out[10]: [[3, 4, 3, 7]]
In [11]: max_sublists([0,1,2,3,0,1,3,5,2],[1,2,3,4,5,1,3,5,3,7,3])
Out[11]: [[1, 2, 3], [1, 3, 5]]

虽然不是很漂亮,也不是很快。

您只需要弄清楚如何比较原始子列表中的每个子列表,但这应该很容易。

[编辑:我修复了一个错误并阻止了您的错误发生。]

【讨论】:

  • 优雅!谢谢!!您为“if”循环寻找连续出现的 2 个匹配项,这很聪明。这样可以节省时间。我遇到的唯一小问题是“max_len”行出现错误。我认为这是因为有时只有一个交叉点(或没有),并且它期望至少运行一次“for”循环......或类似的东西。我还没弄明白。
  • 不客气!您的 max_len 行上的问题很可能只是 Python2.X 与 Python 3.X。如果您使用的是 Python 2.X,则可能有两个将该行写为:max_len = max([len(subl) for subl in subls])(因此,使用方括号强制首先在 max 函数中进行列表理解)。我希望这有效!
  • 顺便说一句,我想我在for j in range(len(list2)-2): 的行中打错了,应该只减去 1(你可以看到我在哪里感到困惑。;-) -- 我会重新测试和编辑。跨度>
  • 原来 max_len 行错误更简单。你可能得到了ValueError: max() arg is an empty sequence,所以我修复了函数以在找不到匹配的子列表时返回一个空列表。我还修正了一个错误,导致一些测试出错(昨天我很累)。
  • 发现错误!我在 sublists() 的末尾键入了“print”而不是“return”。哈哈。我认为甚至没有必要告诉 max_sublists() 返回一个空列表,因为 sublists() 已经默认返回一个空列表。感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 2014-12-27
  • 1970-01-01
  • 2023-02-04
相关资源
最近更新 更多