【问题标题】:Remove all but 1 object in list based on grouping根据分组删除列表中除 1 个对象之外的所有对象
【发布时间】:2015-09-25 12:32:14
【问题描述】:

我有一个包含多个属性的对象列表。这是对象。

public class DataPoint
{
    private readonly string uniqueId;
    public DataPoint(string uid)
    {
        this.uniqueId = uid;
    }

    public string UniqueId
    {
        get
        {
            return this.uniqueId;
        }
    }

    public string ScannerID { get; set; }

    public DateTime ScanDate { get; set; }
}

现在在我的代码中,我有一个巨大的列表,可能有几百个。

每个数据点对象都属于某种类型的扫描仪,并且有一个扫描日期。我想删除在同一天扫描的所有数据点,给定机器的最后一个除外。

我尝试如下使用 LINQ,但这不起作用。我还有很多重复的数据点。

this.allData = this.allData.GroupBy(g => g.ScannerID)
                   .Select(s => s.OrderByDescending(o => o.ScanDate))
                   .First()
                   .ToList();`

我需要按扫描仪 ID 对数据点进行分组,因为可能在同一天但在不同的机器上扫描了数据点。如果有多个,我只需要一天的最后一个数据点。

为澄清而编辑 - 最后一个数据点是指给定机器的给定扫描日期的最后一个扫描数据点。我希望这会有所帮助。因此,当按扫描仪 ID 分组时,我尝试按扫描日期排序,然后只保留最后一次扫描日期进行多次扫描。

这是两台机器的一些测试数据:

Unique ID   Scanner ID      Scan Date
A1JN221169H07  49374    2003-02-21 15:12:53.000
A1JN22116BK08  49374    2003-02-21 15:14:08.000
A1JN22116DN09  49374    2003-02-21 15:15:23.000
A1JN22116FP0A  49374    2003-02-21 15:16:37.000 
A1JOA050U900J  80354    2004-10-05 10:53:24.000 
A1JOA050UB30K  80354    2004-10-05 10:54:39.000 
A1JOA050UD60L  80354    2004-10-05 10:55:54.000 
A1JOA050UF80M  80354    2004-10-05 10:57:08.000 
A1JOA0600O202  80354    2004-10-06 08:38:26.000 

【问题讨论】:

  • 您知道您可以将其设为只读自动属性并摆脱支持字段public string UniqueId { get; private set; }
  • 您还应该为该测试数据提供所需的结果。

标签: c# .net linq list


【解决方案1】:

我想删除在同一天扫描的所有数据点,对于给定机器的最后一个除外。

所以我假设您想同时按ScanDateScannerID 进行分组。这是代码:

var result = dataPoints.GroupBy(i => new { i.ScanDate.Date, i.ScannerID })
                       .OrderByDescending(i => i.Key.Date)
                       .Select(i => i.First())
                       .ToList();

【讨论】:

  • 它会订购ScanDate,以便您可以使用Last吗?
  • 这将根据ScanDateScannerID进行分组,如果最后一个他是指最后输入的值,那么这就足够了,但如果他指的是最后一个日期,那么我必须编辑我的答案。
  • 我认为您实际上想在 i.ScanDate.Date 上进行分组,因为 OP 说 在同一天扫描。然后通过ScanDate订购。
  • 如果OrderByDescending 那么First,而不是Last ;)
  • 抱歉,我指的是按日期计算的最后一个数据点。我将编辑我的问题。谢谢
【解决方案2】:

如果我理解正确,这就是你想要的。

var result = dataPoints.GroupBy(i => new { i.ScanDate.Date, i.ScannerID })
                       .Select(i => i.OrderBy(x => x.ScanDate).Last())
                       .ToList();

这按扫描仪 ID 和日期分组(SacnnerDate.Date 会将时间部分归零),然后对于每个分组它按 ScanDate 排序(因为这些组是同一天,这将按时间排序)并采取最后一个。因此,对于每个扫描仪,您每天都会得到一个结果,其中包含该特定日期的最新 ScanDate

【讨论】:

    【解决方案3】:

    顺便说一句,类可以定义为

    public class DataPoint
    {
      public DataPoint(string uid)
      {
        UniqueId = uid;
      }
    
    public string UniqueId {get; private set; }
    public string ScannerID { get; set; }
    public DateTime ScanDate { get; set; }
    

    }

    【讨论】:

    • 这真的应该是评论而不是答案。有点像我已经发表的评论。
    • @juharr,对不起,当你添加评论时我正在打字。但是,我想展示需要的代码行数如何减少,这对于评论来说太大了。这就是为什么我以Just as an aside为前缀。
    猜你喜欢
    • 1970-01-01
    • 2013-01-06
    • 2022-07-27
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 2018-07-08
    • 1970-01-01
    相关资源
    最近更新 更多