在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”)和两次-自
和至
,计算为来自所收集组的最小/最大时间
- 有关使用相邻分组的
的实现,请参见
自
值/最大直到
值的计算。目前,它只返回它们-您想创建一个新的实例,例如Ceo
,还是重用一个现有实例(例如组中的第一个实例)?这确实非常聪明,为什么我没有在分组上下文中考虑解决方案。。。我确实需要使用反射来创建新实例,因为Since/Until只能通过构造函数传入。但我明白了。谢谢。@Jeffrey:它实际上不是一个由组成的群组(您需要使用我的博客中的替代实现来让它按您的需要工作)。但是,您要执行的操作具有与group by
相同的结构,这使得可能会错误地使用LINQ对其进行良好编码:-)