![](/img/trans.png)
[英]Linq Efficiently find if collection contains duplicates using IQueryable.GroupBy
[英]How to find overlapping in collection using LINQ ( not duplicates but to find overlaps)
List<StoreDetailDto> items = new List<StoreDetailDto>();
items.Add(new StoreDetailDto { StoreNumber = 2, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 3, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 6, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 7, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 9, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 6, WarehouseNumber = 4202, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 7, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 9, WarehouseNumber = 4203, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
items.Add(new StoreDetailDto { StoreNumber = 9, WarehouseNumber = 4207, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1"});
我在上面的集合中,商店6、9之間有重疊,但是商店7沒有重疊,這是重復項。 我發現相同的商店和不同的倉庫重疊。
為了確保我正在執行以下操作:
var overlapDupStores = items.GroupBy(
u => u.StoreNumber,
u => { return u; },
(key, g) => g.ToList())
.ToList()
.Where(cnt => cnt.Count() > 1);
foreach (var dpovl in overlapDupStores)
{
var stores = dpovl.Where(g => g.IsResolved != true).GroupBy(u => new { u.StoreNumber, u.WarehouseNumber }).ToList();
if (stores.Count() > 1)
{
response.OverlappingStores.AddRange(stores.SelectMany(gr => gr).ToList());
}
}
我首先找到重復的商店,它將在對象內部具有對象,其中對象的重復數為count = 2,然后按商店編號和倉庫編號分組,不同商店和倉庫的數量仍為2,但對於相同的商店和重復倉庫它將是count = 1,所以我發現count> 1,因此我可以找到重復項並檢查Isresolved是否在解決后不再再次拉同一個存儲。
以下是小提琴:
使用LINQ的GroupBy().Select().Where()
嘗試此操作,根據顯示的輸出,根據我假設的條件對對象列表進行分組和過濾。
說明:
GroupBy() =>
使用StoreNumber
屬性對對象進行StoreNumber
。
Select() =>
選擇IsResolved
屬性為false
的對象
Where() =>
過濾具有超過1個元素且具有不同WarehouseNumber
SelectMany()=>
平分組,以使所有匹配的對象處於順序視圖中
如果需要,可以添加OrderBy()
以對StoreNumber
ThenBy()
WarehouseNumber
上的列表進行StoreNumber
。
根據使用情況, Duplicates
過濾器可能不正確。 可能有必要對其進行調整。
var Duplicates =
items.GroupBy(store => store.StoreNumber)
.Select(grp => grp.Where(store => store.IsResolved == false))
.Where(stores => stores.Count() > 1 && stores.Select(w => w.WarehouseNumber).Distinct().Count() == 1)
.SelectMany(stores => stores)
.ToList();
var Overlapping =
items.GroupBy(store => store.StoreNumber)
.Select(grp => grp.Where(store => store.IsResolved == false))
.Where(store => store.Count() > 1 && store.Select(w => w.WarehouseNumber).Distinct().Count() > 1)
.SelectMany(stores => stores)
.ToList();
Overlapping.ForEach(ovr =>
Console.WriteLine($"{ovr.StoreNumber} " +
$"{ovr.WarehouseNumber} " +
$"{ovr.IsResolved} " +
$"{ovr.StoreName} " +
$"{ovr.WarehouseName}"));
此Overlapping
列表打印:
6 4201 False StoreEx WarehouseEx1
6 4202 False StoreEx WarehouseEx1
9 4201 False StoreEx WarehouseEx1
9 4203 False StoreEx WarehouseEx1
9 4207 False StoreEx WarehouseEx1
此Duplicates
列表打印:
7 4201 False StoreEx WarehouseEx1
7 4201 False StoreEx WarehouseEx1
我認為這些查詢可以完成工作:
var overlaps =
items
.GroupBy(x => new { x.StoreNumber, x.WarehouseNumber })
.GroupBy(x => x.Key.StoreNumber)
.Where(x => x.Skip(1).Any())
.Where(x => !x.Any(y => y.Any(z => z.IsResolved)))
.SelectMany(x => x.SelectMany(y => y))
.ToList();
var duplicates =
items
.GroupBy(x => new { x.StoreNumber, x.WarehouseNumber })
.GroupBy(x => x.Key.StoreNumber)
.Where(x => !x.Skip(1).Any())
.Where(x => x.First().Skip(1).Any())
.Where(x => !x.Any(y => y.Any(z => z.IsResolved)))
.SelectMany(x => x.SelectMany(y => y))
.ToList();
我使用了以下源數據:
var items = new List<StoreDetailDto>()
{
new StoreDetailDto { StoreNumber = 2, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 3, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 6, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 7, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 9, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 6, WarehouseNumber = 4202, IsResolved = true, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 7, WarehouseNumber = 4201, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 9, WarehouseNumber = 4203, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
new StoreDetailDto { StoreNumber = 9, WarehouseNumber = 4207, IsResolved = false, StoreName = "StoreEx", WarehouseName = "WarehouseEx1" },
};
值得注意的是,如果7要擁有帶有新WarehouseNumber
的第三條記錄,則它將出現在overlaps
結果中並將在其中包含重復項。
如果我正確理解您的意思。 以下將給您您想要的。
var warehouseCountsByStore =
from item in items
group item by new { item.StoreNumber, item.WarehouseNumber } into store
where store.Count() != 0
select new
{
store.Key.StoreNumber,
store.Key.WarehouseNumber,
Count = store.Count()
};
var storesWithDuplicateWarehouses =
from warehouse in warehouseCountsByStore
where warehouse.Count != 1
select new { warehouse.StoreNumber };
var storesWithMultipleWarehouse =
from item in items
group item by new { item.StoreNumber } into store
where store.Count() > 1
&& storesWithDuplicateWarehouses.Any(x => x.StoreNumber != store.Key.StoreNumber)
select new
{
store.Key.StoreNumber
};
Console.WriteLine("Duplicates");
foreach (var store in storesWithDuplicateWarehouses)
Console.WriteLine(store.StoreNumber);
Console.WriteLine("Overlap");
foreach (var store in storesWithMultipleWarehouse)
Console.WriteLine(store.StoreNumber);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.