如何使用 LINQ 在集合中查找重叠(不是重复而是查找重叠)

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());
    }
}

我首先找到重复的商店,它会在对象内部包含计数 = 2 的重复商店的对象,然后按商店编号和不同商店的仓库编号分组,仓库计数仍为 2,但对于同一商店和仓库是重复的,它将是 count = 1,所以我发现 count > 1 这样我就可以找到重复项并检查 Isresolved 在解决后不要再次拉同一个商店。

下面是fiddle:

https://dotnetfiddle.net/TknnkJ

如果我没理解错的话。下面就给你想要的。

   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);

试试这个,使用 LINQ 的 GroupBy().Select().Where() 根据我假设您需要的标准对对象列表进行分组和过滤,给定您显示的输出。

描述:

GroupBy() => Groups the objects using the StoreNumber property.
Select() => Selects the objects where the IsResolved property is false
Where() => Filters the objects that have more than 1 elements with different WarehouseNumber
SelectMany()=> Flattens the Grouping, to have all the matching objects in a sequential view

如果需要,可以添加

OrderBy() 以对 StoreNumber ThenBy() WarehouseNumber.

上的列表进行排序

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 结果中,并会在其中包含重复项。