2014-11-07 3 views
1

У меня есть 4 класса, каждый из которых наследуется от одного и того же базового класса. Все они имеют свойство Id & Path. Когда мои данные загружаются из xml, я строю 4 списка на основе этих классов.Найти дубликаты в нескольких списках с помощью linq

У меня есть следующий код, который позволяет мне сравнить 2 списка:

var list1 = settings.EmailFolders.Select(m => m.Path).ToList(). 
Intersect(settings.LogPaths.Select(m=>m.Path).ToList()).ToList(); 

, но я хотел бы

  1. Я хочу, чтобы сравнить 1-й список других 3 и найти, если существует повторяющийся путь.

  2. Если ничего не найдено, я тогда хочу применить ту же логику сравнения второго списка и сравнить его с другим 2.

  3. Если ничего не найдено, я тогда хочу применить ту же логику, сравнивающую третий список и сравнить его с последним.

Пожалуйста, обратите внимание, что я не хочу, пункт 1, 2 и 3 в одном процессе, как я хотел бы сообщить соответствующую ошибку, если дубликаты найдены.

Если я повторно использовать выше и добавить дополнительный Intersect с дополнительным списком,

var list1 = settings.EmailFolders.Select(m => m.Path).ToList(). 
Intersect(settings.LogPaths.Select(m=>m.Path).ToList()). 
Intersect(settings.SuccessPaths.Select(m=>m.Path).ToList()). 
Intersect(settings.FailurePaths.Select(m=>m.Path).ToList()).List(); 

выше хотел бы нанесение and оператора между собой, а не or оператора, который не то, что я хочу. Мне нужно знать, если какой-либо из пути, используемого в FailurePaths или LogPaths или SuccessPaths уже используются в моей EmailFolder.Path

UPDATE:

Я обновил свой вопрос с ответом на основе @Devuxer предложения это правильный ответ, но вместо работы с строковым массивом я основываю его на списке классов, все из которых содержат свойство Path.

List<EmailFolder> emailFolders = LoadEmailFolders(); 
List<LogPath> logPaths = LoadLogPaths(); 
List<SuccessPath> successPaths = LoadSuccessPaths(); 
List<FailurePath> failurePaths = LoadFailurePaths(); 

var pathCollisions = EmailFolders.Select(a=>a.Path) 
.Intersect(LogPaths.Select(b=>b.Path)) 
.Select(x => new { Type = "LogPath", Path = x }) 
.Concat(EmailFolders.Select(c=>c.Path) 
.Intersect(SuccessPaths.Select(d=>d.Path)) 
.Select(x => new { Type = "SuccessPath", Path = x })) 
.Concat(EmailFolders.Select(e=>e.Path) 
.Intersect(FailurePaths.Select(f=>f.Path)) 
.Select(x => new { Type = "FailurePath", Path = x })).ToList(); 

Обратите внимание, что в приведенном выше пример, для простоты, я только что объявил мой список с функцией для каждого, которые загружаются соответствующие данные, но в моем случае, все данные десериализируются и загружаются сразу.

ответ

0

Я могу быть немного недопонимания ваших требований, но похоже, что вы хотите что-то вроде этого:

var emailFolders = new[] { "a", "b", "c" }; 
var logPaths = new[] { "c", "d", "e" }; 
var successPaths = new[] { "f", "g", "h" }; 
var failurePaths = new[] { "a", "c", "h" }; 

var pathCollisions = emailFolders 
    .Intersect(logPaths) 
    .Select(x => new { Type = "Email-Log", Path = x }) 
    .Concat(emailFolders 
     .Intersect(successPaths) 
     .Select(x => new { Type = "Email-Success", Path = x })) 
    .Concat(emailFolders 
     .Intersect(failurePaths) 
     .Select(x => new { Type = "Email-Failure", Path = x })); 

Это приводит к :

Type   | Path 
-------------------- 
Email-Log  | c 
Email-Failure | a 
Email-Failure | c 
-------------------- 

Если это то, что вы искали, Intersect определенно правильный путь, чтобы найти дубликаты. Я просто добавил некоторые статьи Concat и предоставил Type, чтобы вы могли видеть, какой тип столкновения пути произошел.

Редактировать

Ну пули в вашем вопросе, кажется, просит что-то, отличное от последнего предложения вашего вопроса.

Если вы действительно хотите, чтобы все сравнения, один из способов сделать это, чтобы добавить больше Concat пунктов:

var pathCollisions = emailFolders 
    .Intersect(logPaths) 
    .Select(x => new { Type = "Email-Log", Path = x }) 
    .Concat(emailFolders 
     .Intersect(successPaths) 
     .Select(x => new { Type = "Email-Success", Path = x })) 
    .Concat(emailFolders 
     .Intersect(failurePaths) 
     .Select(x => new { Type = "Email-Failure", Path = x })) 
    .Concat(logPaths 
     .Intersect(successPaths) 
     .Select(x => new { Type = "Log-Success", Path = x })) 
    .Concat(logPaths 
     .Intersect(failurePaths) 
     .Select(x => new { Type = "Log-Failure", Path = x })) 
    .Concat(successPaths 
     .Intersect(failurePaths) 
     .Select(x => new { Type = "Success-Failure", Path = x })); 

Это не «короткое замыкание», как вы задумали, хотя (так он найдет all столкновение пути, а не остановка после первого типа), но он должен по крайней мере предоставить вам данные, необходимые для создания отчета.

+0

Я должен попробовать то, что вы предложили. Это заставило меня улыбнуться :) с изумлением, как то, что можно сделать в linq, и как мало я до сих пор не знаю об этом предмете. Поистине удивительно! То, что у вас есть, выглядит хорошо, но вместо применения массивов строк я хочу применить это к списку объектов. – Thierry

+0

@Thierry. Чтобы мой пример работал на вашу ситуацию, я думаю, что вы можете просто сделать 'new {Type =" Email-Log ", Path = x.Path} для каждого' нового' оператора. – devuxer

+1

Отлично! Это сработало очарование! Я обновлю свой вопрос с ответом, где я использую список объектов, каждый из которых имеет свойство Path. Благодарю. – Thierry

0

Вы можете использовать Содержит используя свойство для сравнения

var result = list1.Where(x => list2.Contains(x.Path)); 

Это даст все предметы из list1 которые также в list2

Если вы хотите только счетчик затем использовать.Count() в конце

То же правило применяется для сравнения 3 других списков

Смежные вопросы