2015-12-03 33 views
2

我有一個例如List<string> ListProviderKeys的列表,其中包含一些值。 我也有從下面一類的第二列表,例如List<ChangesSummary> SecondList;從另一個列表中存在的列表中排除項目

public class ChangesSummary 
{ 
    public string TableName { get; set; } 
    public string ProviderKey { get; set; } 
    public string ProviderAdrsKey { get; set; } 
    public string ProviderSpecialtyKey { get; set; } 
    public string FieldName{ get; set; } 
} 

試想一下,第一個列表保存的是同一種價值觀的我們把ProviderKey領域在第二列表中的值。 現在我想要修剪第二個列表,只有他們的ProviderKey不是已經在第一個列表中的值。 我該怎麼做?我知道操作員除了但不知道如何在這種情況下應用它!

+1

有運算符'Exclude'。嘗試使用它 –

+0

使用除了兩個列表必須具有相同的值,因此您需要將其中一個的類型轉換爲另一個的類型以根據您的條件應用除了 – Zinov

回答

1

我能想到的最好的是:

A)創建字典和使用它的快速查找

B)使用LINQ .Where該字典中的.ContainsKey()方法在內部使用Hashtable並執行快速查找。

這將減少搜索複雜到幾乎O(1)而非O(N) RO惡化(當我們使用LINQ .Where().Any().Contains(),並導致嵌套循環)。

MSDN page來自:

辭典的通用類提供從一組鍵的映射到 一組值。字典中的每個添加項都包含一個值 及其關聯的鍵。使用其密鑰檢索值非常快,接近於O(1),因爲Dictionary類實現爲 散列表。

所以我們可以做的是:

Dictionary<string, string> dict = ListProviderKeys.ToDictionary(s => s); 

var newList = SecondList.Where(e => !dict.ContainsKey(e.ProviderKey)).ToList(); 

這裏是說明它並測試其性能非常簡單的,短的,但完整的例子:

class Person 
{ 
    public int Id { get; set; }   
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<int> ints = new List<int>(); 
     List<Person> People = new List<Person>(1000); 

     for (int i = 0; i < 7500; i++) 
     { 
      ints.Add(i); 
      ints.Add(15000 - i - 1); 
     } 

     for (int i = 0; i < 45000; i++) 
      People.Add(new Person() { Id = i }); 

     Stopwatch s = new Stopwatch(); 

     s.Start(); 

     // code A (feel free to uncomment it)   
     //Dictionary<int, int> dict = ints.ToDictionary(p => p); 

     //List<Person> newList = People.Where(p => !dict.ContainsKey(p.Id)).ToList(); 

     // code B 
     List<Person> newList = People.Where(p => !ints.Contains(p.Id)).ToList(); 

     s.Stop(); 

     Console.WriteLine(s.ElapsedMilliseconds); 
     Console.WriteLine("Number of elements " + newList.Count); 

     Console.ReadKey(); 
    } 

發佈模式結果爲:

代碼A &代碼B輸出30個000元件,而是:

花了超過2000毫秒,代碼B和只有5代碼毫秒甲

+0

上使用這些代碼是有道理的,但它與我跑過的示例崩潰。 – Bohn

+0

List firstList = new List (); firstList.Add(「fdsfd」); firstList.Add(「sdfvf」); firstList.Add(「P2」);firstList.Add(「P4」); – Bohn

+0

@Bohn我提供了簡短的例子 – Fabjan

-1

我認爲在這種情況下,簡單Where會更容易,更易於應用。

var first = new List<string> { "a" }; 
var second = new List<ChangesSummary>() 
{ 
    new ChangesSummary() { ProviderKey = "a" }, 
    new ChangesSummary() { ProviderKey = "b" } 
}; 

var result = second.Where(item => !first.Contains(item.ProviderKey)); 

// result 
// .ToList() 
// .ForEach(item => Console.WriteLine(item.ProviderKey)); 
+0

Downvote?真?謹慎闡述? –

+0

對不起,應該工作,我在我自己的例子中有複製粘貼錯誤,我在 – Bohn

-2

我相信這將工作:

List<ChangesSummary> ExceptionList = SecondList. 
Where(x => !ListProviderKeys.Any(key => x.ProviderKey == key)).ToList(); 
0
public class Programm 
    { 
     public static void Main() 
     { 
      List<ChangesSummary> summaries = new List<ChangesSummary>(); 

      summaries.Add(new ChangesSummary() 
      { 
       FieldName = "1", 
       ProviderKey = "Test1", 
      }); 

      summaries.Add(new ChangesSummary() 
      { 
       FieldName = "2", 
       ProviderKey = "Test2", 
      }); 

      summaries.Add(new ChangesSummary() 
      { 
       FieldName = "3", 
       ProviderKey = "Test3", 
      }); 

      List<string> listProviderKeys = new List<string>(); 

      listProviderKeys.Add("Test1"); 
      listProviderKeys.Add("Test3"); 

      var res = summaries.Where(x => !listProviderKeys.Contains(x.ProviderKey)); 


      res.ToList().ForEach(x => Console.WriteLine(x.ProviderKey)); 

      Console.ReadLine(); 
     } 
    } 

    public class ChangesSummary 
    { 
     public string TableName { get; set; } 
     public string ProviderKey { get; set; } 
     public string ProviderAdrsKey { get; set; } 
     public string ProviderSpecialtyKey { get; set; } 
     public string FieldName { get; set; } 
    } 
+0

didnn't與我的例子: – Bohn

+0

你運行的例子嗎?這是你的輸入數據? – Zinov

+0

對不起,應該工作,我在我自己的例子中,我使用這些代碼複製粘貼錯誤。 – Bohn

相關問題