【问题标题】:How to find the difference between two lists consisted of different data types with Python如何使用 Python 查找由不同数据类型组成的两个列表之间的差异
【发布时间】:2022-01-07 17:11:32
【问题描述】:

说明:

A型:

([1, 2, 3, 4, 5, 6, 7, 8], [1, 3, 4, 5, 6, 7, 8]) ➞ 2

B型:

([True, True, False, False, True], [False, True, False, True]) ➞ True

C 型:

(["Jane", "is", "pretty", "ugly"], ["Jane", "is", "pretty"]) ➞ "ugly"

类型 D:

(["different", "types", "5", 5, [5], (5,)], ["5", "different", [5], "types", 5]) ➞ (5,)

进展: 对于空调,我会先把它们分成两组,然后用set.difference()或“-”来找出区别。但是这个方法不适用于B,但是我仍然可以使用“Counter()”来获取每个元素的重复次数,然后找出差异。

问题: 现在我被D困住了。 我认为无论是“set.difference()”还是“-”或“Counter()”,它们都可以很好地处理由相同数据类型组成的列表,但 D 由字符串、整数、列表、元组组成,即,不同的数据类型,那么在Python中如何处理呢?

下一步: 对我来说,最直接的方法是找到一个至少可以计算 D 中这些元素的类型的函数,这样我就可以先比较它们,然后再讨论这些元素的值。是不是好办法?

【问题讨论】:

    标签: python list types


    【解决方案1】:

    一种蛮力方法是遍历第二个列表中的项目,从第一个列表中删除该项目:

    a = ["different", "types", "5", 5, [5], (5,)]
    b = ["5", "different", [5], "types", 5]
    
    a_copy = a.copy()
    for x in b:
        a_copy.remove(x)
    print(a_copy) # [(5,)]
    

    假定ba 的子列表(最多排列)。

    【讨论】:

    • 真巧,我在 1 秒前测试它
    【解决方案2】:

    主要问题是集合元素和字典键(计数器内部使用字典)必须是可散列的,但不能保证两个给定列表中的元素是可散列的。在您的示例 D 中,有一个列表 [5],它是不可散列的,因为它是可变的。

    根据Python docs

    大多数 Python 的不可变内置对象都是可散列的;可变容器(例如列表或字典)不是;不可变容器(例如元组和frozensets)只有在它们的元素是可散列的时候才是可散列的。

    如果您可以在输入列表中获得的项目没有限制,那么如果不使用蛮力解决方案,这个问题似乎很困难:将第一个列表中的每个元素与第二个列表中的每个元素进行比较。

    • 如果有匹配项:从第二个列表中删除匹配项。
    • 如果没有匹配项,请将其添加到包含列表差异的第三个列表中。
    • 如果需要保留,请使用 .copy() 预先制作列表副本。

    最后,将第二个列表中剩余的所有元素移动到第三个列表中并返回。

    这个算法效率不高:如果第一个列表的大小为 n,第二个列表的大小为 m,则需要 O(nm) 时间。但鉴于我们无法对输入做出假设,这可能是必要的。


    或者,如果我们可以假设一维子列表是我们将在输入列表中看到的唯一不可散列的类型,我们可以通过将列表转换为其可散列对应物:元组来规避这个问题。我们仍然可以使用您的 Counter 想法,但现在我们必须区分 (5,)[5]。这是我的想法:

    • 我们存储元组 (type(x), x),而不是在 Counter 中存储元素 x。
    • 例外情况是如果 x 是一个列表,在这种情况下我们存储 (type(x), tuple(x))
    • (5,) 存储为 (<class 'tuple'>, (5,))
    • [5] 存储为 (<class 'list'>, (5,))

    现在您可以简单地比较计数器来找出差异。这比蛮力解决方案要快,但您必须不断添加异常,因为您在输入列表中允许越来越多的不可散列元素(如 set -> freezeset)。使用这种方法,有时您必须对输入可以包含的内容设置一些限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 2015-05-26
      • 2022-11-22
      • 2018-07-16
      • 1970-01-01
      • 2019-11-23
      • 2015-03-19
      相关资源
      最近更新 更多