我正在尝试使用列表列表进行一些操作。
我有一个包含一些属性的列表。我已根据GroupId Property将列表拆分为子列表。
我将列表中的每个列表项分配给另一个类。但在这里我不得不使用2 ForEachs。是否有任何方法可以在一个中进行,这样我就可以在输入列表中输入超过10000个列表项的大量输入时提高性能。下面是我试过的代码
class Comp
{
public int CompId { get; set; }
public string CompName { get; set; }
public int GroupId { get; set; }
}
class EmpComp
{
public int EmpCompId { get; set; }
public string EmpCompName { get; set; }
public int EmpId { get; set; }
public int GroupId { get; set; }
}
#region Input
List<Comp> compList = new List<Comp>();
compList.Add(new Comp { CompId = 1, CompName = "One", GroupId = 1 });
compList.Add(new Comp { CompId = 2, CompName = "Two", GroupId = 1 });
compList.Add(new Comp { CompId = 3, CompName = "One", GroupId = 2 });
compList.Add(new Comp { CompId = 4, CompName = "Three", GroupId = 1 });
compList.Add(new Comp { CompId = 5, CompName = "One", GroupId = 4 });
compList.Add(new Comp { CompId = 6, CompName = "Two", GroupId = 4 });
#endregion
var groupedCompList = compList.GroupBy(u => u.GroupId ).Select(grp => grp.ToList()).ToList();
List<EmpComp> empCompList = new List<EmpComp>();
int empId = 0;//Just for reference
groupedCompList.ForEach(x =>
{
x.ForEach(y =>
{
EmpComp empComp = new EmpComp();
empComp.EmpCompId = y.CompId;
empComp.EmpCompName = y.CompName;
empComp.GroupId = y.GroupId ;
empComp.EmpId = empId + 1;
empCompList.Add(empComp);
});
empId++;
});
我想避免在这里使用两个ForEach。
注意:我有一些其他的ID和字符串需要根据GroupId进行分配。 empId只是一个例子
答案 0 :(得分:3)
不需要嵌套的ForEach
甚至是SelectMany
,因为创建的组只是被嵌套的ForEach
展平。实际上当前代码是不正确的,因为DisplayOrder
属性在调用GroupBy
时并没有真正排序 - 只是在每个不同的DisplayOrder
的第一个值按顺序排列时源数据。如果不是,那么结果就会失灵。
这可以在没有ForEach
的任何分组或使用的情况下工作,并且它正确地命令结果:
List<EmpComp> empCompList =
compList
.OrderBy(u => u.DisplayOrder)
.Select((y, n) => new EmpComp()
{
EmpCompId = y.CompId,
EmpCompName = y.CompName,
DisplayOrder = y.DisplayOrder,
EmpId = n + 1,
}).ToList();
感谢评论,我意识到原始代码在内循环之外有empId++;
。
这是解决问题的代码:
List<EmpComp> empCompList =
compList
.OrderBy(u => u.DisplayOrder)
.GroupBy(u => u.DisplayOrder)
.Select((ys, n) =>
ys
.Select(y => new EmpComp()
{
EmpCompId = y.CompId,
EmpCompName = y.CompName,
DisplayOrder = y.DisplayOrder,
EmpId = n + 1,
}))
.SelectMany(x => x)
.ToList();
这给出了这个结果:
答案 1 :(得分:1)
这样怎么样(调整了Enigmativity的答案):
int empId=0;
Dictionary<string, int> displayOrderTable = compList.GroupBy(u => u.DisplayOrder).Distinct().ToDictionary(x=>x.Key, (v,k)=>empId++;)
List<EmpComp> empCompList =
compList
.OrderBy(u => u.DisplayOrder)
.Select((y, n) => new EmpComp()
{
EmpCompId = y.CompId,
EmpCompName = y.CompName,
DisplayOrder = y.DisplayOrder,
EmpId = displayOrderTable[y.DisplayOrder],
}).ToList();
这将在O(N + N)= O(N)时间内运行,而不是O(N ^ 2)(使用for in)。
答案 2 :(得分:1)
以下是仅使用LINQ
的代码var empCompList = compList
.GroupBy(c => c.GroupId)
.SelectMany((g, i) => g.Select(c => new EmpComp
{
EmpCompId = c.CompId,
EmpCompName = c.CompName,
GroupId = c.GroupId,
EmpId = i + 1
}))
.ToList();
关键是使用接收源元素和索引的SelectMany overload。