【问题标题】:Get only unique elements from a list仅从列表中获取唯一元素
【发布时间】:2013-12-22 00:16:31
【问题描述】:

有一个包含 deviceIds 和要在设备上执行的相应操作的列表。

var results= new List<Result>
{
    new Result{ DeviceId= 1, ActionType = 1 },
    new Result{ DeviceId= 1, ActionType = 2 },
    new Result{ DeviceId= 1, ActionType = 3 },
    new Result{ DeviceId= 2, ActionType = 1 },
    new Result{ DeviceId= 3, ActionType = 1 },
    new Result{ DeviceId= 4, ActionType = 1 },
    new Result{ DeviceId= 5, ActionType = 1 },
    new Result{ DeviceId= 6, ActionType = 1 },
    new Result{ DeviceId= 6, ActionType = 2 },

};

如何过滤列表中唯一的 deviceIds(没有 DeviceId 1),并将其分配回 var "results"

results = List<Result>
{
    new Result{ DeviceId= 2, ActionType = 1 },
    new Result{ DeviceId= 3, ActionType = 1 },
    new Result{ DeviceId= 4, ActionType = 1 },
    new Result{ DeviceId= 5, ActionType = 1 },
};

已尝试使用 groupby,但无法继续前进

   results =  from result in results
              group result by result.DeviceId
              into groupedResultsByDevice
              where groupedResultsByDevice.Count() == 1
              select ????

【问题讨论】:

    标签: c# linq list group-by unique


    【解决方案1】:

    除了用查询语法回答之外,在方法语法 LINQ 查询中,它将是:

    results = results.GroupBy(r => r.DeviceId)
                     .Where(g => g.Key != 1 && g.Count() == 1)
                     .Select(g => g.First())
                     .ToList();
    

    【讨论】:

    • g.Key有什么意义!=1
    • @canceo,我以为你想过滤掉它,但现在我什至不确定我为什么会这样想。所以你可以简单地删除这个条件。
    【解决方案2】:

    分组后,您可以选择第一个(也是组中唯一的元素):

    results =  from result in results
              group result by result.DeviceId
              into groupedResultsByDevice
              where groupedResultsByDevice.Count() == 1
              select groupedResultsByDevice.First(); // <---
    

    【讨论】:

      【解决方案3】:
      results =  from r in results
                 group r by r.DeviceId into g
                 where g.Count() == 1
                 select g.First()
      

      您可以将g.Count() 替换为!g.Skip(1).Any() 更高效:

      results =  from r in results
                 group r by r.DeviceId into g
                 where !g.Skip(1).Any()
                 select g.First()
      

      一旦找到第二个元素,它将返回false,而不是计算组中的所有项目。

      【讨论】:

      • 为什么不select g.Single()
      • 如果g is empty 那么!g.Skip(1).Any() 还有true?
      【解决方案4】:

      看看这个

          public static void Main()
          {
              var results = new List<Result>
                                {
                                    new Result {DeviceId = 1, ActionType = 1},
                                    new Result {DeviceId = 1, ActionType = 2},
                                    new Result {DeviceId = 1, ActionType = 3},
                                    new Result {DeviceId = 2, ActionType = 1},
                                    new Result {DeviceId = 3, ActionType = 1},
                                    new Result {DeviceId = 4, ActionType = 1},
                                    new Result {DeviceId = 5, ActionType = 1},
                                    new Result {DeviceId = 6, ActionType = 1},
                                    new Result {DeviceId = 6, ActionType = 2},
                                };
              List<Result> result = results
                  .GroupBy(x => x.DeviceId)
                  .Where(x => x.Count() == 1)
                  .SelectMany(x => x)
                  .Distinct()
                  .ToList();
      
              result.ForEach(Console.WriteLine);
      
              Console.ReadLine();
          }
      
      public sealed class Result : IEqualityComparer<Result>
      {
          public int DeviceId { get; set; }
      
          public int ActionType { get; set; }
      
          public bool Equals(Result x, Result y)
          {
              if (ReferenceEquals(x, y)) return true;
              if (ReferenceEquals(x, null)) return false;
              if (ReferenceEquals(y, null)) return false;
              if (x.GetType() != y.GetType()) return false;
              return x.DeviceId == y.DeviceId && x.ActionType == y.ActionType;
          }
      
          public int GetHashCode(Result obj)
          {
              unchecked
              {
                  return (obj.DeviceId*397) ^ obj.ActionType;
              }
          }
      
          public override string ToString()
          {
              return string.Format("DeviceId: {0}, ActionType: {1}", DeviceId, ActionType);
          }
      }
      

      结果输出:

      DeviceId: 2, ActionType: 1
      DeviceId: 3, ActionType: 1
      DeviceId: 4, ActionType: 1
      DeviceId: 5, ActionType: 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-17
        • 1970-01-01
        • 2012-12-16
        • 2017-08-11
        • 2021-11-23
        • 2016-01-14
        相关资源
        最近更新 更多