2014-11-07 123 views
1

我有4個類都從相同的基類繼承。他們都有一個Id &路徑屬性的共同點。當我的數據從xml加載時,我建立了基於這些類的4個列表。使用linq查找多個列表中的重複項

我有下面的代碼,讓我比較2所列出:

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

但我想

  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 })); 

這不「短路」你希望的方式,雖然(所以它會找到全部路徑衝突,而不是在第一種類型之後停止),但它至少應爲您提供生成報告所需的數據。

+0

我必須嘗試一下你的建議。它讓我感到驚訝,因爲在linq中可以做什麼,而對於這個問題我還不知道。真的很棒!你有什麼看起來不錯,但不是應用字符串數組,而是想將它應用到對象列表。 – Thierry 2014-11-07 01:11:57

+0

@Thierry,爲了讓我的例子適用於您的情況,我認爲您可以爲每個'new'語句執行'new {Type =「Email-Log」,Path = x.Path}'。 – devuxer 2014-11-07 01:19:05

+1

完美!它起到了魅力!我將用我在使用每個都有Path屬性的對象列表的答案更新我的問題。謝謝。 – Thierry 2014-11-07 01:21:54

0

可以使用包含通過使用屬性來比較

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

它將給所有從列表1如果你想只計數然後用這也在列表2

的項目。COUNT()在結束

同樣的規則適用於比較其他3所列出