我有一个通用列表ItemList
,如果每个ListID
不包含所有可能的ItemIDs
,那么我想将它们从列表中删除。
我将在下面用数据的简化版本说明:
MaxItemID = 4
ListID ItemID
1 1
2 1
2 2
2 3
2 4
3 1
3 2
4 1
4 2
4 3
4 4
5 1
5 2
我想要的数据是:
ListID ItemID
2 1
2 2
2 3
2 4
4 1
4 2
4 3
4 4
我昨天问了一个类似于SQL的问题,并得到了使用Exists
的答案,这很好,但我发现最大数量的项目可能会有所不同,我想我也是我更喜欢使用linq。我认为使用distinct().Count()
技术可以工作,但到目前为止没有成功,听起来这也不是最有效的方法。
非常感谢
答案 0 :(得分:2)
我希望这是你的目的:
var list =
ItemList
.GroupBy(p=>p.ListID)
.Where(p=>p.Distinct().Count()<MaxItemID)
.ToArray()
答案 1 :(得分:2)
int distinctIDs = items.Select(x => x.ItemID).Distinct().Count();
var newList = items
.GroupBy(x => x.ListID)
.Where( x => x.Select(y=>y.ItemID).Distinct().Count() == distinctIDs)
.SelectMany(x => x.ToList())
.ToList();
答案 2 :(得分:2)
试试这个
var query = from baseItem in itemList
group baseItem by baseItem.ListID into gr
where gr.Count() == MaxItemID
join selectItem in itemList on gr.Key equals selectItem.ListID
select selectItem;
var requiredList = query.ToList();
这样做,检查屏幕截图。
修改强>
如果允许重复,则可以将查询修改为
var query = from item in itemList
group item by item.ListID into gr
where gr.Select(s=>s.ItemId).Distinct().Count() == MaxItemID
join i in itemList on gr.Key equals i.ListID
select i;
答案 3 :(得分:0)
无法评论Linq版本的性能,但这里有Linq和非linq解决方案
hth,
艾伦
修改强>
示例数据确实显示了listId / ItemId的任何重复项,因此我省略了不同的检查,但如果需要,它将作为linq语句的第一部分。
修改2
更新了Linq代码。
没有更新非linq代码。在添加之前检查是否与之前相同(假设按照样本输入排序,ListId,ItemId。
[TestMethod]
public void LinqVersion() {
Dictionary<int, List<ListItem>> found = new Dictionary<int, List<ListItem>>();
var comparer = new ListItemEqualityComparer();
var actual = Input.Distinct(comparer).GroupBy(lstItem => lstItem.ListId).Where(grp => grp.Count() == 4).SelectMany(grp => grp);
Assert.IsTrue(Expected.SequenceEqual(actual, comparer));
}
[TestMethod]
public void NoLinqVersion() {
Dictionary<int, List<ListItem>> found = new Dictionary<int, List<ListItem>>();
foreach (var listItem in Input) {
AddItem(found, listItem.ListId, listItem);
}
var actual = new List<ListItem>();
foreach (var pair in found) {
if (pair.Value.Count == 4) {
actual.AddRange(pair.Value);
}
}
Assert.IsTrue(Expected.SequenceEqual(actual, new ListItemEqualityComparer()));
}
private static void AddItem(IDictionary<int, List<ListItem>> dictionary, int listId, ListItem listItem) {
if (!dictionary.ContainsKey(listId)) {
dictionary.Add(listId, new List<ListItem>());
}
dictionary[listId].Add(listItem);
}
public class ListItem {
public int ListId { get; set; }
public int ItemId { get; set; }
}
public class ListItemEqualityComparer : IEqualityComparer<ListItem> {
public bool Equals(ListItem x, ListItem y) {
return x.ListId == y.ListId && x.ItemId == y.ItemId;
}
public int GetHashCode(ListItem obj) {
return obj.ListId ^ obj.ItemId;
}
}
public List<ListItem> Input = new List<ListItem>(){
new ListItem{ ListId = 1 , ItemId = 1},
new ListItem{ ListId = 2 , ItemId = 1},
new ListItem{ ListId = 2 , ItemId = 2},
new ListItem{ ListId = 2 , ItemId = 3},
new ListItem{ ListId = 2 , ItemId = 4},
new ListItem{ ListId = 3 , ItemId = 1},
new ListItem{ ListId = 3 , ItemId = 2},
new ListItem{ ListId = 4 , ItemId = 1},
new ListItem{ ListId = 4 , ItemId = 2},
new ListItem{ ListId = 4 , ItemId = 3},
new ListItem{ ListId = 4 , ItemId = 4},
new ListItem{ ListId = 5 , ItemId = 1},
new ListItem{ ListId = 5 , ItemId = 2},
};
public List<ListItem> Expected = new List<ListItem>{
new ListItem{ ListId = 2 , ItemId = 1},
new ListItem{ ListId = 2 , ItemId = 2},
new ListItem{ ListId = 2 , ItemId = 3},
new ListItem{ ListId = 2 , ItemId = 4},
new ListItem{ ListId = 4 , ItemId = 1},
new ListItem{ ListId = 4 , ItemId = 2},
new ListItem{ ListId = 4 , ItemId = 3},
new ListItem{ ListId = 4 , ItemId = 4}
};