【问题标题】:How to combine elements of a list如何组合列表的元素
【发布时间】:2011-01-25 04:59:10
【问题描述】:

我正在使用 C#。我有一个排序的结构列表。该结构有一个存储月份和年份的 DateTime 对象和一个存储值的整数。该列表按日期排序。我需要遍历列表并将其组合,以便每个日期只有一个结构实例。

例如: 我的初始列表如下所示:

{ (Apr10, 3), (Apr10, 2), (Apr10, -3), (May10, 1), (May10, 1), (May10, -3), (Jun10, 3) } 

结果列表应如下所示:

{ (Apr10, 2), (May10, -1), (Jun10, 3) }

我正在寻找一种简单/高效的解决方案。

结构是:

struct CurrentTrade
{
    public DateTime date;
    public int dwBuy;
}

名单是:

private List<CurrentTrade> FillList

【问题讨论】:

  • 可变结构是邪恶的。此外,您不应使用 dw 前缀。
  • @SLaks: Im 可变结构是邪恶的?...我希望这是你的错误。
  • Addie,是类还是结构体?
  • @zneak:已修复。我不敢相信我写的。
  • @Addie:结构应该是不可变的,这意味着在现有结构创建后不能更改它的值。您应该将字段替换为只读属性,并提供一个将它们作为参数的构造函数。

标签: c# algorithm list arraylist


【解决方案1】:

您可以使用 LINQ:

var newList = (
    from trade in FillList
    group trade by trade.Date.Date into g
    select new CurrentTrade { date = g.Key, dwBuy = g.Sum(t => t.dwBuy) }
).ToList();

【讨论】:

【解决方案2】:

如果您不想使用 LINQ:

如果列表按日期排序,则具有相同日期的所有项目都彼此相邻。你可以这样做:

for ( int i = FillList.Count - 1; i >= 1; i-- ) {
    if ( FillList[i].date == FillList[i-1].date ) {
       FillList[i-1].dwBuy += FillList[i].dwBuy;
       FillList.RemoveElementAt( i );
    }
}

如果您的 .NET 支持,建议使用 LINQ 解决方案。

如果输入日期包含时间组件,并且您想在日期上合并,只需将 if 语句更改为:

if ( FillList[i].date == FillList[i-1].date )

if ( FillList[i].date.Date == FillList[i-1].date.Date )

【讨论】:

  • 这行不通。 (交易时间不同)另外,它不会正确处理同一日期的三笔交易。
  • 该语句确实只明确说明了日期(尽管在 DateTime 中),但如果包含时间,则更改是微不足道的。
  • 这实际上是我在发布此问题之前开始使用并遇到问题的方法。
  • 您遇到了什么问题?我在第一次编辑时有一个错字 - 如果您更改 for 循环的顺序应该没问题。
  • 问题在于我的方法而不是你的方法。感谢您的帮助,我采用了 LINQ 方法,效果很好!
【解决方案3】:

【讨论】:

    【解决方案4】:
    var result  = FillList.GroupBy(x => x.date)
                          .Select(g => new CurrentTrade { 
                              date = g.Key, 
                              dwBuy = g.Sum(x => x.dwBuy) 
                          })
                          .ToList();
    

    编辑:

    如果 CurrentTrade 确实包含时间组件,则应将其转换为仅限日期的 DateTime 对象:

    var result  = FillList.GroupBy(x => x.date.Date)
                          .Select(g => new CurrentTrade { 
                              date = g.Key, 
                              dwBuy = g.Sum(x => x.dwBuy) 
                          })
                          .ToList();
    

    【讨论】:

    • 不一定,取决于OP中没有显示的代码。如果 CurrentTrade 是用例如构造的date = DateTime.Now.Date 这将起作用。样本数据根本不包含时间,所以拉里和我只是根据 OP 的事实做了一个假设。
    【解决方案5】:

    使用HashSet&lt;T&gt; 怎么样? HashSet 不能两次包含同一个对象。但是,这可能需要您在 CurrentTrade 类中重新实现 GetHash 方法。

    (不过像return Date.GetHashCode() ^ dwBug 这样简单的东西也可以做到。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 2016-12-19
      • 1970-01-01
      • 2020-07-19
      • 2020-05-22
      • 1970-01-01
      • 2019-04-21
      相关资源
      最近更新 更多