合并来自两个列表的信息

Combining information from two lists

我有两个List对象,一个记录通过,一个记录失败。我构建了两个单独的列表,因为它们分别显示在 Excel 电子表格中。

两个列表都包含 ReportData 个对象,这些对象具有以下字段:

DataDate (DateTime)
quantity (int)
rejected (int)
cumulativeQuantity (int)
cumulativeRejected (int)

在通过列表中,我记录了日期、数量和截止到该日期的累计数量。 rejected 和 cumulativeRejected 值设置为零。我对失败的列表做相反的事情。

最后,我想将它们组合起来得到一个包含所有日期的 List<ReportData> 对象。

我不想让列表相交,因为从技术上讲没有交集。虽然日期可能存在于两者中,但对象并不相同。我考虑过遍历 pass 列表,查找失败中存在的日期,然后记录它们的 rejected 和 cumulativeRejected 值。这导致的问题是,如果有不存在的日期,我可能不知道要为该日期设置什么 cumulativeRejected

另一个问题是如果一个项目存在失败但没有通过。在实践中,不应该发生,但出于本示例的意图和目的,它可能会发生。

有办法吗?这几乎是列表的交集和并集的组合,我不知道该怎么做。

编辑

如果有点不清楚,考虑两个列表:

pass:
   DataDate: 05/01/15 quantity: 10 cumQuantity: 10 rejected: 0 cumRejected: 0
   DataDate: 05/02/15 quantity: 15 cumQuantity: 25 rejected: 0 cumRejected: 0
   DataDate: 05/03/15 quantity: 10 cumQuantity: 35 rejected: 0 cumRejected: 0
   DataDate: 05/04/15 quantity: 15 cumQuantity: 50 rejected: 0 cumRejected: 0

fail:
   DataDate: 05/01/15 quantity: 0 cumQuantity: 0 rejected: 10 cumRejected: 10
   DataDate: 05/02/15 quantity: 0 cumQuantity: 0 rejected: 10 cumRejected: 20
   DataDate: 05/03/15 quantity: 0 cumQuantity: 0 rejected: 10 cumRejected: 30
   DataDate: 05/05/15 quantity: 0 cumQuantity: 0 rejected: 10 cumRejected: 40

如何获得如下所示的最终列表:

total:
   DataDate: 05/01/15 quantity: 10 cumQuantity: 10 rejected: 10 cumRejected: 10
   DataDate: 05/02/15 quantity: 15 cumQuantity: 25 rejected: 10 cumRejected: 20
   DataDate: 05/03/15 quantity: 10 cumQuantity: 35 rejected: 10 cumRejected: 30
   DataDate: 05/04/15 quantity: 15 cumQuantity: 50 rejected: 0 cumRejected: 30
   DataDate: 05/05/15 quantity: 0 cumQuantity: 50 rejected: 10 cumRejected: 40

你可以这样做(不是最有效但简短明了):

var combined = passed
    .Concat(failed)
    .GroupBy(x => x.DataDate)
    .Select(x => new ReportData {
        DataDate = x.Key,
        quantity = x.Sum(rd => rd.quantity),
        rejected = x.Sum(rd => rd.rejected),
        cumulativeQuantity = x.Max(rd => rd.cumulativeQuantity), // or Sum
        cumulativeRejected = x.Max(rd => rd.cumulativeRejected)  // or Sum
    }).ToList();

// Fill "holes" for dates not present in both lists.
for (var i = 1; i < combined.Count; i++)
{
    if (combined[i].cumulativeQuantity == 0)
        combined[i].cumulativeQuantity = combined[i - 1].cumulativeQuantity;
    if (combined[i].cumulativeRejected == 0)
        combined[i].cumulativeRejected = combined[i - 1].cumulativeRejected;
}

我很喜欢,所以我会展开:

(如果您的日期范围很大,字典可以加快处理速度,例如它们在这里。这还假设有 没有重复的日期 。如果有请告诉我, 我会相应地调整)

这假设您是两种不兼容的类型The <TSource> is not the same

var passedDict = passed.ToDictionary(p => p.DataDate, p);
var failedDict = failed.ToDictionary(p => p.DataDate, p);

var startedOn = DateTime.....
var endedOn = DateTime....

var combined = Enumerable
  .Range(0, 1 + endedOn.Subtract(startedOn).Days)
  .Select(x => 
    {
      Pass pass;
      Fail fail;

      var result = new ReportData()
      result.DataDate = staredOn.AddDays(x),

      if (passedDict.TryGetValue(result.DataDate, out pass))
      {
        result.Quantity = pass.Quantity;
        result.CumulativeQuantity = pass.CumulativeQuantity;
      }

      if (failedDict.TryGetValue(result.DataDate, out fail))
      {
        result.Rejected= fail.Rejected;
        result.CumulativeRejected = fail.CumulativeRejected ;
      }

      return result;
    })
  .ToList();