Я мог бы попробовать обратный индекс, element -> [IDs of containing lists]
.Итерация по индексу покажет вам, какие списки имеют общие элементы, и, следовательно, не может быть подключена.
- Шаг 1: создать обратный индекс
- Шаг 2: создать индекс несовместимости,
list ID -> [IDs of incompatible lists]
- Шаг 3: перебрать карту несовместимости для объединения совместимых списков.
Шаг 3 может быть более сложным, если существуют определенные правила для объединения совместимых списков, поскольку совместимость не является 't transient.
Некоторая псевдо-Java: Ради себя, я собираюсь предположить, что структуры данных выглядят так (вероятно, мой Bin
- это ваш Row
, более или менее):
class Bin {
ID id;
LinkedList<Element> list;
}
Набор корзин allBins
имеет тип Collection<Bin>
.
Шаг 1. Обратный индекс имеет тип MultiValueMap<Element, ID>
.То есть каждый элемент сопоставляется с набором идентификаторов (ячеек, содержащих этот элемент).
MultiValueMap<Element, ID> reverseIndex;
for (Bin bin : allBins) {
for (Element e : bin) {
reverseIndex.put(e, bin.id);
}
}
Шаг 2. Индекс несовместимости имеет тип MultiValueMap<ID, ID>
, где каждый идентификатор ячейки сопоставляется снабор идентификаторов бинов несовместимых бинов.
MultiValueMap<ID, ID> incompatibilityIndex;
for (Element e : reverseIndex.keySet()) {
List<ID> binsWithE = reverseIndex.get(e);
for (ID id : binsWithE) {
incompatibilityIndex.putAll(id, binsWithE); // each bin is incompat with itself
}
}
Шаг 3: Теперь мы можем объединить любые два бина, которых нет в карте несовместимости друг друга.Поскольку объединение двух корзин изменяет несовместимость, мы должны быть хитрее:
Set<Bin> binsRemainingToProcess; // == original allBins
Set<Bin> binsProcessed; // == new allBins
while (binsRemainingToProcess.size() > 0) {
Bin bin = // grab any bin to work on from binsRemainingToProcess
// grab any compatible bins
// could iterate until we find one, but I'm going to compute all compatible
List<ID> compatibleBinIDs = // all bin IDs in binsRemaining...
List<ID> incompatibleBinIDs = incompatibilityIndex.get(bin.id);
compatibleBinIDs.removeAll(incompatibleBinIDs);
if (compatibleBinIDs.size() > 0) {
Bin otherBin = // some bin with ID in compatibleBinIDs
// joining the two bins -- means joining the inner lists,
// but also joining the incompatibilities
joinDataStructures(bin, otherBin);
incompatibilityIndex.putAll(bin.id, incompatibilityIndex.get(otherBinID));
// we don't need the other bin anymore, but we may be able to join
// the first bin to others
binsRemainingToProcess.remove(otherBin);
} else {
// couldn't join with anyone; we're done with this bin and can move on
binsRemainingToProcess.remove(bin);
binsProcessed.add(bin);
}
}
Хорошо, так что последний оказался намного более подробным, чем я планировал ...