2014-06-10 74 views
2

刪除項目我有一個看起來像對象:從列表,其中不*所有*位置

public class ListItem { 
    public int ItemId { get; set; } 
    public int LocationId { get; set; } 
    // ... other properties ... 
} 

我從數據庫加載這些項目(List<ListItem>)的列表。這些由物品ID 位置ID唯一。我碰巧知道總共只有10個位置(位置1到10)。

有沒有LINQ聲明我可以寫刪除不出現在的所有項目 10個地點?

我現在擁有的是一樣的東西:

myList.RemoveAll(x => 
     // this line would need repeated 10 times to work! 
     !myList.Any(y => y.ItemId == x.ItemId && y.LocationId == 1) && 
     !myList.Any(y => y.ItemId == x.ItemId && y.LocationId == 2) 
     // etc... 
    ); 

由於這只是一個檢查區域我要重複所有地區 - 不是很優雅的代碼。任何想法或幫助表示讚賞!

回答

5

可以使用的GroupBy到組由ItemId的元素,然後刪除那些沒有10個項目在分組的所有元素: -

var itemsNotAtAllLocations = myList.GroupBy(x => x.ItemId) 
            .Where(g => g.Count() != 10) 
            .Select(g => g.Key); 

myList.RemoveAll(x => itemsNotAtAllLocations.Contains(x.ItemId)); 

或者,如果你喜歡的查詢語法: -

var itemsNotAtAllLocations = from item in mylist 
          group item by item.ItemId into g 
          where g.Count() != 10 
          select g.Key; 

還有在評論中建議做,而不是執行以下操作: -

myList.RemoveAll(x => myList.Count(y => y.ItemId == x.ItemId) != 10); 

我會提供以下反饋意見: -

  1. 爲了清晰而不是簡潔,我將在此進行優化。很多開發人員發現密集的LINQ很難閱讀,並且明確的意圖聲明(itemsNotAtAllLocations)可以節省大量時間。

  2. 你的版本保存了創建一個(可能很小的)數據結構,但代價是更多的時候迭代(推測是大的)數據結構。 Prima facie這聽起來像更多的工作給我,而不是更少。

  3. 我非常懷疑這種性能影響會非常顯着。

  4. 如果績效對您很重要,您應該在現實條件下設置以利益相關方爲中心的基準和衡量標準。

  5. 如果表現對你非常重要,我希望你可以通過採取不同的方法做得更好,你可以在數據庫層進行查詢,還是可以首先使用更合適的數據結構(即代表天生的分組)?

+0

啊,是的,這是一個很好的觀點。該去喝咖啡了。 –

+1

這是一個好主意!是否有一個性能分支用於使用相同的計數想法如下:'myList.RemoveAll(x => myList.Select(y => y.ItemId == x.ItemId).Count()<10);'? –

+0

@drew_w,你可以將代碼縮小到myList.RemoveAll(x => myList.Count(y => y.ItemId == x.ItemId)<10);' –

0

使用IList.Contains()這樣的:

var locationIds = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

myList.RemoveAll(x => !myList.Any(y => y.ItemId == x.ItemId && locationIds.Contains(y.LocationId)); 
+3

這不起作用,它只檢查每個記錄是否屬於有效的位置ID,它不確定該記錄是否存在於所有位置。 – James

+0

對不起,讓我編輯。 –

0
var test1 = from g in myList 
    group g by g.ItemId into grp 
    select new { key = grp.Key, cnt = grp.Count() }; 

只是檢查,看看是否計數爲10,關鍵是良好的。

相關問題