【问题标题】:GroupBy with ternary operatorGroupBy 与三元运算符
【发布时间】:2012-09-20 19:23:27
【问题描述】:

我有一个 Person 对象:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    public double Height { get; set; }
    public bool IsTest { get; set; }
}

然后我有一个列表,其中包含不同的Person 对象。

我想知道是否有办法在 LINQ 中使用三元运算符和 GroupBy,具体取决于对象的某些属性。例如:

var groupedPersons = persons.GroupBy(person => person.IsTest ? 
                      new {
                              person.Name, 
                              person.Age, 
                              person.Address
                           } 
                     : new {
                              person.Name, 
                              person.Age, 
                              person.Address, 
                              person.Height}).ToList();

但不幸的是,这不起作用,给了我例外

无法确定条件表达式的类型,因为存在 'AnonymousType#1' 和 'AnonymousType#2' 之间没有隐式转换

这是否可以实现?如何实现?

谢谢

编辑:试过了,但没用。

var groupedPersons = persons.GroupBy(person => person.OnTest ? 
                     new Person { 
                                   Address = person.Address, 
                                   Name = person.Name, 
                                   Age = person.Age } 
                     : new Person { 
                                   Address= person.Address, 
                                   Name = person.Name, 
                                   Age = person.Age , 
                                   Height = person.Height}).ToList();

编辑:让它工作,看看我的回答

【问题讨论】:

  • 您是否尝试过选择新的“人员”而不是使用匿名类?
  • 哦,谢谢...这很简单 :)
  • 我很惊讶选择 Person 的作品,除非你的 person 类实现了 Equals() 和 GetHashCode()。如果这是 EF,那么我很确定它不会让您选择实体类的新实例。
  • 是的,你是对的,这不能正常工作,但我设法让它工作:) 看看我的答案......

标签: c# linq group-by


【解决方案1】:

可以使用匿名对象。您只需确保它们具有相同的字段名称和字段类型:

var groupedPersons = persons.GroupBy(person => person.IsTest ? 
                      new {
                              person.Name, 
                              person.Age, 
                              person.Address,
                              Height = 0
                           } 
                     : new {
                              person.Name, 
                              person.Age, 
                              person.Address, 
                              person.Height}).ToList();

编辑:现在我想了想,您可以在分配Height 时使用三元运算符来节省一些代码行。如果您担心身高为 0 的人与测试人分组,您也可以按IsTest 分组。

var groupedPersons = persons.GroupBy(person => 
                      new {
                              person.Name, 
                              person.Age, 
                              person.Address,
                              Height = person.IsTest ? 0 : person.Height,
                              person.IsTest
                           }).ToList();

【讨论】:

    【解决方案2】:

    您不能单独使用三元组作为组的一部分,因为编译器无法确定 GroupBy 调用的返回类型(因为它实际上是两种不同的类型)。

    您可以将逻辑嵌入到 Person 对象的属性中:

    public class Person {
      public string Name { get; set; }
      public int Age { get; set; }
      public string Address { get; set; }
      public double Height { get; set; }
      public bool IsTest { get; set; }
      public double GroupProperty { get { return IsTest ? 0.0 : Height } }
    }
    
    var groupedPersons = persons.GroupBy(person =>
      new {
            person.Name,
            person.Age,
            person.Address,
            person.GroupByProperty
      }).ToList();
    

    这将消除Height 属性作为所有Person 实例的分组值,其中IsTest 设置为true(因为它们都将共享相同的高度)。

    【讨论】:

    • 除了你的代码实际上没有使用Person,它会创建一个匿名类型的对象。
    【解决方案3】:

    好的,在尝试了此处显示的一些示例后,我意识到这行不通,我让它以其他方式工作。这是我如何做到的一个例子:

    var groupedPersons = 
           persons.GroupBy(
                     person =>
                          person.Name + "|" +
                          person.Age.ToString() + "|" +
                          person.Address + "|" +
                          (person.IsTest ? null : person.Height.ToString())
          .ToList();
    

    因此,如果有一个 Person 的属性为 IsTest = false,那么它也会使用 person.Height 进行分组。

    【讨论】:

    • 这样做是个坏主意,字符串不是你应该用来表示任何东西的通用类型。
    • 实际上在我的真实对象中(在项目中而不是此处的人)中,所有分组的属性都是字符串。还有一个布尔属性。然后根据布尔值,我是否需要再按一个属性分组。
    • 所以我问,这是否可以实现以及如何实现 - 我找到了一个解决方案。如果这是一个问题和否决案例,我也可以将我的示例 Person 类的属性更改为字符串。
    • 这不是某些属性不是字符串的问题。问题是,如果非必要,您不应该使用字符串来表示结构化数据。
    • Name: Barack|51 Age: 51 Address: The White House 将与Name: Barack Age: 51 Address: 51|The White House 分组。这似乎不太可能发生,但最好的做法是尽量减少所有潜在错误。但我意识到这是唯一适合您的解决方案。 my solution 出了什么问题?我相信我编辑的版本可以解决任何潜在的问题。
    猜你喜欢
    • 1970-01-01
    • 2020-10-25
    • 2021-05-12
    • 1970-01-01
    • 2017-09-27
    • 2011-06-17
    • 2023-03-12
    • 1970-01-01
    • 2018-09-10
    相关资源
    最近更新 更多