比较两个无序列表并查找 pyspark 中哪些元素不匹配

comparing two unordered lists and finding which elements are mismatched in pyspark

从这个 post here 进一步提出问题,我有两个无序列表,想看看它们是否相等,同时考虑重复项而不关心顺序。如果它们不相等,则查找哪个列表中的哪些元素不在另一个列表中。

以上面post为例,假设等号左边的列表是L1,等号右边的列表是L2,

    L1                               L2
['one', 'two', 'three'] == ['one', 'two', 'three'] :  true
['one', 'two', 'three'] == ['one', 'three', 'two'] :  true
['one', 'two', 'three'] == ['one', 'two', 'three', 'three'] :  false, L1:'three'
['one', 'two', 'three'] == ['one', 'two', 'three', 'four'] :  false, L1:'four'
['one', 'two', 'three'] == ['one', 'two', 'four'] :  false, L1:'four', L2:'three'
['one', 'two', 'three'] == ['one'] :  false, L2:'two','three'

输出不必完全像我描述的那样,但基本上我想知道两个列表的比较是真还是假,如果是假,L2 中的哪些元素不在 L1 中,哪些元素不在 L1 中在 L1 中不在 L2 中。

@Katriel 提供的解决方案是像这样使用 collections 函数:

import collections
compare = lambda x, y: collections.Counter(x) == collections.Counter(y)

但它没有提供有关哪些元素不匹配的信息。 在 pyspark 中是否有有效的方法来执行此操作?

如果在您的示例中不需要保留像 row3 这样的重复匹配项,那么您可以使用 double array_except 和 concat 来获取输出,并使用 'when,otherwise' 根据大小获取布尔值阵列产生。 (spark2.4+)

df.withColumn("result", F.concat(F.array_except("L1","L2"),F.array_except("L2","L1")))\
  .withColumn("Boolean", F.when(F.size("result")==0,F.lit(True)).otherwise(F.lit(False))).show(truncate=False)

+-----------------+------------------------+-------------+-------+
|L1               |L2                      |result       |Boolean|
+-----------------+------------------------+-------------+-------+
|[one, two, three]|[one, two, three]       |[]           |true   |
|[one, two, three]|[one, three, two]       |[]           |true   |
|[one, two, three]|[one, two, three, three]|[]           |true   |
|[one, two, three]|[one, two, three, four] |[four]       |false  |
|[one, two, three]|[one, two, four]        |[three, four]|false  |
|[one, two, three]|[one]                   |[two, three] |false  |
+-----------------+------------------------+-------------+-------+

您不需要在比较之前删除重复项,因为 array_except 会自动为您完成。