比较两个无序列表并查找 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 会自动为您完成。
从这个 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 会自动为您完成。