2011-02-23 40 views
23

我有一個很長的ID(整數)的列表代表所有當前在我的數據庫中的項目減去一個巨大的名單:如何從另一個有效的C#

var idList = GetAllIds(); 

我也有另外一個巨大的通用清單與商品添加到數據庫:現在

List<T> itemsToAdd; 

,我想從泛型列表的ID已經在IDLIST刪除所有項目。 目前IDLIST是一個簡單的數組和我減去名單如下:

itemsToAdd.RemoveAll(e => idList.Contains(e.Id)); 

我敢肯定,這可能是快了很多,所以我應該用什麼樣的數據類型爲兩個集合,什麼是最有效的做法減去它們?

謝謝!

+0

如果可能的話,我想知道如何進行流/枚舉... – drzaus 2016-11-30 19:22:59

回答

17

變換暫時idListHashSet<T>並使用相同的方法,即:

items.RemoveAll(e => idListHash.Contains(e.Id)); 

應該更快

+1

謝謝 - 這的確速度更快,而且是我做的! – Shackles 2011-02-23 14:36:43

2

您應該使用兩個HashSet<int> s。
請注意,它們是獨特的和無序的。

22

LINQ可以幫助:

itemsToAdd.Except(idList) 

你的代碼是緩慢的,因爲List<T>.ContainsO(n)。所以你的總成本是O(itemsToAdd.Count*idList.Count)

您可以將idList變成HashSet<T>其中有O(1).Contains。或者只是使用Linq .Except擴展方法,它爲你做。

請注意,.Except也將刪除左側的所有重複項。即新的int[]{1,1,2}.Except(new int[]{2})只會導致{1},第二個被移除。但我認爲你的情況沒有問題,因爲ID通常是唯一的。

+0

請注意,這也將排除來自'itemsToAdd'的任何重複項。這是否是一個問題取決於OP(我懷疑不是因爲他們已經在他們的例子中使用'RemoveAll')。 – LukeH 2011-02-23 14:09:46

+0

@LukeH我只是在編輯它。 – CodesInChaos 2011-02-23 14:10:31

+0

+1,謝謝你的出色解釋!我現在將idList構建爲Hashset ,但無法使用.Except(),因爲itemsToAdd的類型爲List/HashSet ,而idList的類型爲HashSet 。它雖然更快,並滿足我的需求。 – Shackles 2011-02-23 14:39:48

5

假設以下前提是真實的:

  • idListitemsToAdd可能不包含重複值
  • 您正在使用.NET Framework 4。0

你可以使用一個HashSet<T>這樣:

var itemsToAddSet = new HashSet(itemsToAdd); 
itemsToAddSet.ExceptWith(idList); 

根據文檔的ISet<T>.ExceptWith方法相當有效:

這種方法複雜度爲O(n)的操作, 其中n是 ,其他參數中元素的個數。

您的情況nidList中的項目數。

+0

問題是itemsToAdd的類型是HashSet 而idList的類型是HashSet 。因此,我不能在這兩個方面調用ExceptWith,並需要將idList轉換爲會消耗大量內存的Hashset 。 – Shackles 2011-02-23 14:35:35

+0

'idList'不一定是'HashSet ',你只需要從'itemsToAdd'中創建一個HashSet。然後,您將'idList'傳遞給'HashSet .ExceptWith'作爲'IEnumerable '。 – 2011-02-23 14:57:21