сравнение двух неупорядоченных списков и поиск несоответствующих элементов в pyspark - PullRequest
1 голос
/ 04 марта 2020

Продолжая вопрос из этого поста здесь , у меня есть два неупорядоченных списка, и я хотел бы выяснить, равны ли они, принимая во внимание дубликаты и не заботясь о порядке. И если они не равны, чтобы найти, какие элементы из какого списка не входят в другой.

Взяв пример из поста, упомянутого выше, предполагая, что список слева от знака равенства - это 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 не находятся в L2.

Решение, предоставленное @Katriel, заключалось в использовании функции collections следующим образом:

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

Но он не предоставляет информацию о том, какие элементы не совпадают. Есть ли эффективный способ сделать это в pyspark?

1 Ответ

2 голосов
/ 04 марта 2020

Если сохранение дублирующих совпадений, таких как row3, в вашем примере не является необходимым, то вы можете использовать double array_except с concat для получения выходных данных и использовать 'when, иначе', чтобы получить логическое значение на основе размера созданного массива. (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 сделает это автоматически.

...