按某个“列”对List <list <string >>进行排序

时间:2019-04-16 13:53:37

标签: c# linq

示例输入和当前输出,不进行排序:

List<List<string>> _optoGrid = new List<List<string>>();

_optoGrid.Add(new List<string>() {"10",     "10",     "100",    "20",    "10",     "10"});
_optoGrid.Add(new List<string>() {"20",     "20",     "50",     "10",    "1546",   "555"});
_optoGrid.Add(new List<string>() {"30",     "30",     "10",     "10",    "10",     "100"});
_optoGrid.Add(new List<string>() {"30",     "30",     "10",     "1",     "10",     "100"});

显示这是排序代码的位置。

foreach (List<string> list in _optoGrid)
{
    foreach (string s in list)
    {
        Console.Write(s + ", ");
    }

    Console.WriteLine();
}

当前输出:

  

10,10,100,20,10,10,

     

20,20,50,10,1546,555,

     

30,30,10,10,10,100,

     

30,30,10,1,10,100,

期望的输出假定按第5列排序(从0开始):

  

20,20,50,10,1546,555,

     

30,30,10,10,10,100,

     

30,30,10,1,10,100,

     

10,10,100,20,10,10,

我想输入:

_optogrid.Sort(5) //5 being the 'column' number

3 个答案:

答案 0 :(得分:4)

此代码没有列,它是一个包含列表的列表。 LINQ仍然可以订购结果。在LINQ中对结果进行排序的方法是OrderBy()OrderByDescending()。它的参数是一个lambda,它产生排序键。

在这种情况下,lambda应该返回应该用于订购的列表项,例如:

var  _optoGrid = new List<List<string>>{
    new List<string> {"10",     "10",     "100",     "20",    "10",     "10"},
    new List<string> {"20",     "20",     "50",     "10",     "1546",   "555"},
    new List<string> {"30",     "30",     "10",     "10",     "10",     "100"},
    new List<string> {"30",     "30",     "10",     "1",     "10",     "100"}
};
var orderedResults=_optoGrid.OrderBy(lst=>lst[5]);

var orderedResults=_optoGrid.OrderByDescending(lst=>lst[5]);

那是非常脆弱的代码。不能保证所有列表具有相同数量的项目。忘记一个值或再输入一个值很容易。如果一个列表包含少于6个项目,则.OrderBy(lst=>lst[5])将抛出该错误,但是如果使用了错误个项目,则不会抱怨。

最好使用适当的类而不是列表,尤其是在所有项目都具有相同数量的项目的情况下,例如:

class MyItem
{
    public string ProperlyNamedProperty1{get;set;}
    ...
    public MyItem(string prop1,string prop2,...)
    {
        ProperlyNamedProperty1=prop1;
        ...
    }
}

var  _optoGrid = new List<MyItem>{
    new MyItem("10",     "10",     "100",     "20",    "10",     "10"),
};
var orderedResults=_optoGrid.OrderBy(item=>item.Property6);
如果列表仅在本地使用(例如,以一种方法),则也可以使用

值元组。当然,6个属性太多了:

var  _optoGrid = new List<(string prop1, string prop2, string prop3, string prop4, string prop5, string prop6)>{
    ("10",     "10",     "100",     "20",    "10",     "10"),
    ("20",     "20",     "50",     "10",     "1546",   "555"),
    ("30",     "30",     "10",     "10",     "10",     "100"),
    ("30",     "30",     "10",     "1",     "10",     "100")
};
var orderedResults=_optoGrid.OrderBy(tuple=>tuple.prop6);

如果一个人觉得很懒惰,并且物品的数量不是那么多,则可以省略名称:

var  _optoGrid = new List<(string, string, string, string, string, string)>{
    ("10",     "10",     "100",     "20",    "10",     "10"),
    ("20",     "20",     "50",     "10",     "1546",   "555"),
    ("30",     "30",     "10",     "10",     "10",     "100"),
    ("30",     "30",     "10",     "1",     "10",     "100")
};
var orderedResults=_optoGrid.OrderBy(tuple=>tuple.Item6);

元组的好处是它们是强类型的。没有理由对所有它们都使用相同的类型,例如:

var  _optoGrid = new List<(int, int, string, string, string, double)>{
    (10,     10,     "100",     "20",    "10",    10),
    (20,     20,     "50",     "10",     "1546",  555),
    (30,     30,     "10",     "10",     "10",    100),
    (30,     30,     "10",     "1",     "10",     100)
};
var orderedResults=_optoGrid.OrderBy(tuple=>tuple.Item6);

这避免了另一个棘手的问题,即字典顺序问题。如果我将字符串从"10"更改为"1000" it will *still* appear before "555", because words that start with“ 1” always come before words that start with“ 5”。使用字符串,OrderBy将返回:

10 10 100 20 10   10000 
20 20 50  10 1546 555 

糟糕。

尽管在第六个字段中使用intdouble,我们得到了预期的顺序:

20 20  50 10 1546   555 
10 10 100 20   10 10000 

答案 1 :(得分:1)

每个列表至少包含6个元素,并且项必须按字母顺序(而不是数字)排序:

IEnumerable<List<string>> sortedLists = _optoGrid.OrderByDescending(l => l[5]);

foreach (List<string> l in sortedLists)
{
    Console.WriteLine(string.Join(", ", l);
}

答案 2 :(得分:0)

这看起来像是按特定列号对表格进行排序。

Enumerable.OrderBy将完成这项工作。

Enumerable.OrderBy,它包含一系列TRow个项目和一个keySelector。 keySelector是一个函数,它以TRow作为输入并返回一个必须对序列进行排序的值。

在您的情况下,TRowList<string>。因此,如果您需要按索引为sortColumnIndex的列进行排序,则需要一个带有List<String> row并返回row[sortColumnIndex]

的KeySelector。

如何?

int sortColumnIndex = 5; //按第5列排序    列表> unorderedList = ...    清单orderedList = unorderedList.OrderBy(row => row [sortColumnIndex]);

简单的漫画卓悦!