ForEach for Linq中的列表

时间:2015-12-09 08:00:07

标签: c# linq list foreach

我正在尝试使用列表列表进行一些操作。

我有一个包含一些属性的列表。我已根据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只是一个例子

3 个答案:

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

这给出了这个结果:

empCompList

答案 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