OrderBy / ThenBy循环 - C#中的嵌套列表

时间:2012-01-27 18:11:55

标签: c# linq

我有一个嵌套列表,

List<List<String>> intable;

我想对所有列进行排序。问题是列数取决于用户输入。

像这样排序列表工作正常(假设此示例为4列)

var tmp = intable.OrderBy(x => x[0]);
tmp = tmp.ThenBy(x => x[1]);
tmp = tmp.ThenBy(x => x[2]);
tmp = tmp.ThenBy(x => x[3]);
intable = tmp.ToList();

但是,当我把它放在循环中时,就像这样:

var tmp = intable.OrderBy(x => x[0]);
for (int i = 1; i <= 3; i++)
{
        tmp = tmp.ThenBy(x => x[i]);
}
intable = tmp.ToList();

它不再正常工作,只对第四列进行排序。

2 个答案:

答案 0 :(得分:25)

这是访问修改后的闭包的情况。将代码更改为此代码,它将起作用:

var tmp = intable.OrderBy(x => x[0]);
for (int i = 1; i <= 3; i++) {
    var thisI = i;
    tmp = tmp.ThenBy(x => x[thisI]);
}
intable = tmp.ToList();

Eric Lippert编写了two-part article来描述这个问题。它无法按预期工作的原因 - 简而言之 - 因为当您调用i时,LINQ仅在使用ToList()的最后一个值时进行评估。这和你写的一样:

var tmp = intable.OrderBy(x => x[0]);
tmp = tmp.ThenBy(x => x[3]);
tmp = tmp.ThenBy(x => x[3]);
tmp = tmp.ThenBy(x => x[3]);
intable = tmp.ToList();

答案 1 :(得分:0)

创建比较器

class StringListComparer : IComparer<List<string>>
{
    public int Compare(List<string> x, List<string> y)
    {
        int minLength = Math.Min(x.Count, y.Count);
        for (int i = 0; i < minLength; i++) {
            int comp = x[i].CompareTo(y[i]);
            if (comp != 0) {
                return comp;
            }
        }
        return x.Count.CompareTo(y.Count);
    }
}

然后像这样排序列表

intable.Sort(new StringListComparer());