Чтобы эффективно найти дубликаты, вам нужно отсортировать ID
s по длине, чтобы вы могли минимизировать необходимые сравнения. (Сортировка добавляет некоторые накладные расходы, но значительно уменьшает сравнение, которое необходимо выполнить - в моем тесте, где 9 идентификаторов имеют, а 3 являются дубликатами 8 значений, это 15 сравнений, отсортированных по сравнению с 42 несортированными.) Как только вы их отсортируете по длине, просто сравните каждый с теми, которые равны или длиннее (в случае полных дубликатов), чтобы найти, какие короткие ID
необходимо сохранить, отмечая любые совпадения, чтобы вы могли пропустить их, а затем найти все Model
s заканчиваются найденными совпадениями.
Создайте List
из ID
s, упорядоченных по их длине:
var orderedIDs = testData.TestRecords.Select(tr => tr.ID).OrderBy(id => id.Length).ToList();
Я не думаю, что есть способ сделать это эффективно с LINQ, но вложенный for
l oop пропуск предыдущих совпадений оптимизирует поиск дубликатов.
Во-первых, переменные для отслеживания ID
s and which
идентификаторы уже совпадают:
var dupRecordSubIDs = new List<string>();
var alreadyMatched = new bool[testData.TestRecords.Count];
Теперь l oop через идентификаторы и сохраните более короткие совпадающие идентификаторы:
// foreach ID in length order
for (int n1 = 0; n1 < testData.TestRecords.Count-1; ++n1) {
// skip the ones that already matched a shorter ID
if (!alreadyMatched[n1]) {
// remember if the shorter ID was alrady added
var added_n1 = false;
// compare the ID to all greater than or equal length IDs
for (int n2 = n1 + 1; n2 < testData.TestRecords.Count; ++n2) {
// if not previously matched, see if we have a new match
if (!alreadyMatched[n2] && orderedIDs[n2].EndsWith(orderedIDs[n1])) {
// only add the shorter ID once for new matches
if (!added_n1) {
dupRecordSubIDs.Add(orderedIDs[n1]);
added_n1 = true;
}
// remember which longer IDs are already matched
alreadyMatched[n2] = true;
}
}
}
}
Теперь найдите все Model
s, которые соответствуют одному из идентификаторов с дубликатом:
var modelRecords = testData.Models.Where(m => dupRecordSubIDs.Any(d => m.ID.EndsWith(d))).ToList();