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

在C#中,在泛型列表中合并具有相同类型的项的最有效方法是什么?,c#,generics,list,merge,C#,Generics,List,Merge,例如,我有以下接口和类: 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 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();
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
如果通用列表包含以下项目:

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();
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
我将合并相同的类型,合并自/直到,并收缩列表中的项目,因此输出为:

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();
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
在回答之前,请确保你理解了这个问题,因为我有一段模棱两可的历史,我不想让别人不高兴。因此,如果您觉得“要求”不明确,请发表评论

我的方式有点愚蠢:

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();
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
我只是想知道一定有更好的解决办法

更新:

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();
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
我只是意识到我的“愚蠢的解决方案”不会涵盖超过两个相同类型的连续项目

例如:

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();

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

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

List newList=newlis();
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
}
对于(inti=1;i
如果伪代码按照您的预期工作,我认为它一点也不愚蠢。我不相信你会找到一个简单的捷径来实现你的目标,因为这是一个非常不寻常的算法。一句话:如果这个算法不会一天运行数百万次,并且列表中没有数百万个对象,我就不会担心效率。

我写过:-)

这感觉就像是“分组依据”,只是,您不想对元素进行全局分组。相反,您只希望对输入列表中相邻的元素进行分组。博客文章提供了一些代码,允许您在LINQ查询中更改
groupby
的含义,这样您就可以编写:

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
指定分组应仅对相邻元素进行分组。然后我们可以按类型收集相邻的人群(使用
GetType().Name
作为键)

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

  • 有关使用相邻分组的
    的实现,请参见

你突然在第三个代码块中切换到伪代码,对吗?@Jourke van der Maas,现在好点了吗?我只是想解释一下新对象应该是什么(相同类型的相邻所有项目的组合)。是的,注释更清晰。我也是,意识到太晚了。无论如何,谢谢;-)我之所以这么快,是因为我很好奇你写了什么:)@Jouke van der Maas,如果有两个以上相同类型的物品相邻,会发生什么?类似于列表[0]=管理器、列表[1]=管理器和列表[2]=管理器?@@Jouke van der Maas,我现在认为循环应该从最后一项开始,将当前项与前一项合并为同一类型,并从列表中删除最后一项(如果可能的话),听起来好像有点过了。男人。。。我就是想不起while循环。@jeffrey你说得对,我没想到。至于向后循环,您可以这样做:对于(inti=list.Count-1;i>=0;i--){}根据定义,类型是从IRole派生的。他不是要求一种方法来完成他与IRole的工作,而是要求实现。同意。正如我前面提到的,这是一个特定于应用程序的答案。group by听起来不错,但如何合并像自/直到这样的属性?@Jeffrey:添加了最小
值/最大
直到
值的计算。目前,它只返回它们-您想创建一个新的实例,例如
Ceo
,还是重用一个现有实例(例如组中的第一个实例)?这确实非常聪明,为什么我没有在分组上下文中考虑解决方案。。。我确实需要使用反射来创建新实例,因为Since/Until只能通过构造函数传入。但我明白了。谢谢。@Jeffrey:它实际上不是一个由
组成的
群组(您需要使用我的博客中的替代实现来让它按您的需要工作)。但是,您要执行的操作具有与
group by
相同的结构,这使得可能会错误地使用LINQ对其进行良好编码:-)