У меня есть набор данных, который выглядит следующим образом:
+-----+-----+
|prev |next |
+-----+-----+
| A| B|
| B| C|
| C| D|
+-----+-----+
Таким образом, в основном значения могут образовывать цепочки, в которых столбец next
из одной строки совпадает со значением previous
из другой строки.
И я хочу «свести» его в другой набор данных, который выглядит следующим образом:
+-----+-----+
|prev |next |
+-----+-----+
| A | B|
| A | C|
| A | D|
+-----+-----+
Графически я могу отображаться в виде цепочки преобразования:
A -> B -> C -> D
в
A -> B
A -> C
A -> D
Я выполняю это преобразование, потому что мне нужно объединить этот вычисленный набор данных с двумя другими наборами данных, используя столбцы prev
и next
.
Я создал работающее рекурсивное решение:
public Dataset<Row> flatten(Dataset<Row> transfers) {
Dataset<Row> notChainingTransfers = transfers.as("left").join(
transfers.as("right"),
functions.expr("left.prev = right.next"), "leftanti"
);
Dataset<Row> chainingTransfers = transfers.as("left").join(
transfers.as("right"),
functions.expr("left.pre = right.next")
).select("right.prev", "left.next");
Dataset<Row> union = notChainingTransfers.union(chainingTransfers);
if (chainingTransfers.count() > 0) {
return flatten(union);
} else {
return union;
}
}
Но я чувствую, что это не очень красиво и не эффективно.Он также имеет большой недостаток: когда я получаю неверные данные, образующие круговую цепочку, он переходит в бесконечную рекурсию:
A -> B -> A
Подобной ситуации не должно быть, но было бы неплохо, если бы ябыло решение, которое могло бы справиться с подобными проблемами.
Я ищу несколько советов о том, как улучшить свое решение или альтернативные подходы.