繁体   English   中英

C# Linq 使用多个字段比较列表值并返回不满足条件的项目

[英]C# Linq Comparing List Values using multiple fields and return item which doesn't satisfy the condition

我有一个这样的列表称为结果

{ Id = "8131367", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131368", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 1500.00 }
{ Id = "8131369", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131370", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131371", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131372", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131373", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131374", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131375", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131376", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131377", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 1500.00 }

我需要根据具有相同值的 GId、Share、Type、OPC、IPC 和具有不同值的价格来过滤列表。 所以从列表中第二个和最后一个价格不同所以我需要从列表项中获取价格不同且值相同的 rest 的列表或 Id 属性。

通过使用两个 Foreach 循环,我能够得到我需要的东西,但不幸的是,我被要求将其转换为 LINQ 查询。 这是我试过的

var items = result.Select(r => result.Where(rr => (r.GId == rr.GId) 
                                                   && (r.Share == rr.Share) 
                                                   && (r.Type == rr.Type) 
                                                   && (r.IPC == rr.IPC) 
                                                   && (r.OPC == rr.OPC) 
                                                   && (r.Price != rr.Price))).ToList();

但是从上面的查询中我没有得到我想要的东西,我相信我已经接近我需要的东西,但我缺乏 LINQ 的专业知识。

您可以使用Group by对除Id之外的所有属性进行分组,如以下代码:

var items = result.GroupBy(x => new { x.GId, x.Share, x.Type, x.OPC, x.IPC, x.Price })
    .Where(x => x.Count() == 1)
    .SelectMany(x => x.Take(1))
    .ToList();

演示

foreach(Test item in items)
{
    Console.WriteLine($"Id:{item.Id}, GID:{item.GId}, Price:{item.Price}");
}

结果

Id:8131368, GID:27720, Price:1500
Id:8131377, GID:27721, Price:1500

我希望你觉得这有帮助。

这将起作用,但根本没有优化:

var result2 = result
    .GroupBy(i => new {i.GId, i.Share, i.Type, i.OPC, i.IPC})
    .Select(i1 => i1.LastOrDefault(i2 => i1.Count(i3 => i3.Price == i2.Price) == 1))
    .ToList();

它将返回 ID 为“8131368”和“8131377”的行

编辑此代码有效,但要求可以避免嵌套循环。 用我的评论检查 Sajid 的回答:-)

因此,我需要从价格不同且 rest 的值相同的列表项中获取该列表或 Id 属性

您可以按包含应该相等的属性的值元组进行分组,然后将 select 分组与一个以上的元素:

var itemIds = result
    .GroupBy(r => (r.GId, r.Share, r.Type, r.IPC, r.OPC))
    .Where(g => g.Select(r => r.Price).Distinct().Count() > 1) // or Count() == 2, then next clause can be simplified
    .Select(g => 
    {
        var byPrice = g.GroupBy(r => r.Price).ToList();
        
        if(byPrice.Count > 2)
        {
            throw new Exception("Could not determine base price - more than 2 groups");
        }
        
        if (byPrice.All(gg => gg.Count() == 1))
        {
            throw new Exception("Could not determine base price - multiple groups with single element");
        }
        
        return byPrice.First(gg => gg.Count() == 1).Select(r => r.Id).First();
    })
    .ToList();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM