繁体   English   中英

在C#中通用列表中合并具有相同类型的项目的最有效方法是什么?

[英]What is the most efficient way to merge items with the same type in a generic list in C#?

例如,我有以下接口和类:

public interface IRole {
    DateTime Since {get;}
    DateTime Until {get;}
}

public class Manager : IRole {
    public DateTime Since {get; private set;}
    public DateTime Until {get; private set;}
}
public class Employee : IRole {
    public DateTime Since {get; private set;}
    public DateTime Until {get; private set;}
}
public class Ceo: IRole {
    public DateTime Since {get; private set;}
    public DateTime Until {get; private set;}
}

如果通用列表包含以下项目:

list[0]=new Manager();
list[1]=new Manager();
list[2]=new Employee();
list[3]=new Manager();
list[4]=new Ceo();
list[5]=new Ceo();

并且我将合并相同的类型,组合Since / Until并缩小列表中的项目,因此输出变为:

newList[0]=new Manager() //(Since is from list[0], Until is from list[1])
newList[1]=new Employee() //(list[2])
newList[2]=new Manager() //(list[3])
newList[3]=new Ceo() //(Since is from list[4], Until is from list[5])

在回答之前请确保你理解这个问题,因为我有一个暧昧的历史,我不想让人不安。 如果您觉得“要求”不明确,请发表评论。

我的方式有点愚蠢:

for each item in list
    the current item shall always be merged into the previous item
        check if current item has the same type as the previous item
            get last item from newList and merge last item with current item

我只是想知道必须有一个更好的解决方案。

更新:

我只是意识到我的“愚蠢的解决方案”不会涵盖超过2个相同类型的连续项目。

例:

list[0]=new Manager();
list[1]=new Manager();
list[2]=new Employee();
list[3]=new Manager();
list[4]=new Ceo();
list[5]=new Ceo();
list[6]=new Ceo();

我写了一篇关于此的博客文章 :-)。

它感觉几乎像group by除了你不想全局分组元素。 相反,您只想对输入列表中相邻的元素进行分组。 博客文章提供了一些代码,允许您在LINQ查询中更改group by的含义,因此您可以只编写:

var groups =
  from person in list.WithAdjacentGrouping()
  group person by person.GetType().Name into g
  select new { 
    Type = g.Key,
    Since = new DateTime(g.Select(p => p.Since.Ticks).Min()),
    Until = new DateTime(g.Select(p => p.Until.Ticks).Max())
  }

WithAdjacentGrouping的调用WithAdjacentGrouping分组应仅对相邻元素进行分组。 然后我们可以按类型收集相邻的人群(使用GetType().Name作为键)。

最后,我们返回一个包含类型名称的集合(例如“Ceo”)和两次 - SinceUntil计算为收集组的最小/最大时间。

我不认为你的伪代码是愚蠢的,如果它按你期望的那样工作。 我不相信你会为你想要做的事情找到一个简单的捷径,因为这是一个相当不寻常的算法。 底线:如果这个算法不会每天运行数百万次并且列表中没有数百万个对象,我不会担心效率。

List<IRole> newList = new Lis<IRole>();
for (int i = 1; i < list.Count; i++) // Start at 1, so we can do i - 1 on the first iteration
{
  if (list[i - 1].GetType() != list[i].GetType()) // they're not the same
  {
    newList.Add(list[i - 1]); // so add the first one too
  }
  newList.Add(list[i]); // always add second one
}

我相信这是一项非常具体的要求。 我不确定这是否会得到框架的支持。 如果类型不是直接从IRole派生,会发生什么。 如果有类似IEmployee的东西从IManager派生出来会怎样。 我不确定框架是如何理解应用程序特定的symentics的。

如果问题非常特定于应用程序,您可以使用linq来使用group子句(在类型上)完成此操作。 我之前没有尝试过,因此无法给出确切的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM