【问题标题】:C# Linq Comparing List Values using multiple fields and return item which doesn't satisfy the conditionC# Linq 使用多个字段比较列表值并返回不满足条件的项目
【发布时间】:2026-01-19 03:05:01
【问题描述】:

我有一个这样的列表,名为 result

{ 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 和具有不同值的价格来过滤列表。所以从列表中第二个和最后一个价格不同所以我需要从列表项中获取价格不同且其余值相同的列表或 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 方面的专业知识。

【问题讨论】:

  • 你能用循环发布你以前的代码吗?
  • @Arcord 我现在没有。它的嵌套 foreach 循环如 foreach(var item1 in result) { foreach(var item2 in result) { if(item1.GId == item2.GId && ... item1.Price != item2.Prices) { // 设置 item1. Id 到列表中 } } }
  • 如果您有想要转换为链接查询的代码,那么那就是可能是您应该显示的代码。或者描述你发布的代码如何没有提供预期的结果。
  • GroupBy 通常是获取与某些常见属性相关的项目的好方法。
  • 问题是你想要完成什么并不完全清楚。您是否正在与一组输入值进行比较?还是您想说“所有具有相同 X、Y 和 Z 的行,只返回与同一组中其他价格不同的行”。

标签: c# linq filter


【解决方案1】:

您可以使用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

希望对您有所帮助。

【讨论】:

  • 在这种情况下,他只想拥有一个价格不同的。您可以删除具有超过 1 个元素的组,这样就可以了 :-)
  • @Arcord,我已经更新了答案,我怀疑 OP 是否也需要重复行的一个元素。但是在我重新阅读问题之后,我将所有元素留给 groupby 并且我'm 使用where count == 1,它只给出不重复的行。谢谢。+1
  • @Sajid 这也将返回只有一个 { x.GId, x.Share, x.Type, x.OPC, x.IPC} 元素的组
  • @GuruStron,如果我理解正确,通过这个查询,如果我从groupby 中删除价格,Where(x => x.Count() == 1) 将给出 0,因为我们有 6 + 6 个没有价格和 ID 的重复行。
  • @Sajid add { Id = "8131367", GId = 27722, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 } (unique GId ) 到 OP 的例子中。
【解决方案2】:

这可行,但根本没有优化:

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 的回答 :-)

【讨论】:

    【解决方案3】:

    所以我需要从价格不同而其余值相同的列表项中获取该列表或 Id 属性

    您可以按包含应该相等的属性的值元组进行分组,然后选择具有多个元素的组:

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

    【讨论】:

    • 我认为这个查询返回两个具有不同 GID 和相同价格的元素。
    • 你有另一个问题g 与最后一行冲突:)
    • @Sajid 实际上它适用于我的机器,但为了清晰起见已修复
    最近更新 更多