2017-08-21 46 views
1

我有一个列表,列表中的每个元素都是一个字符串,它包含特定格式的日期和整数:yyyyMMdd_number。C# - 如何排序列表字符串编号linq?

List<string> listStr = new List<string> { "20170822_10", "20170821_1", "20170823_4", "20170821_10", "20170822_11", "20170822_5", 
              "20170822_2", "20170821_3", "20170823_6", "20170823_21", "20170823_20", "20170823_2"}; 

当使用方法listStr.Sort();

结果如下:

20170821_1 
20170821_10 
20170821_3 
20170822_10 
20170822_11 
20170822_2 
20170822_5 
20170823_2 
20170823_20 
20170823_21 
20170823_4 
20170823_6

预期输出:

20170821_1 
20170821_3 
20170821_10 
20170822_2 
20170822_5 
20170822_10 
20170822_11 
20170823_2 
20170823_4 
20170823_6 
20170823_20 
20170823_21

方式:我认为每个串(DAY_NUMBER)将分裂用下划线,然后比较和按数字排序。 但请建议我LINQ解决方案或更好的方法来排序在这种情况下。

回答

8

由于日期是在可字典顺序进行排序的格式,你可以通过日期前缀使用字符串排序排序,并通过解析整数解决关系:

var sorted = listStr 
    .OrderBy(s => s.Split('_')[0]) 
    .ThenBy(s => int.Parse(s.Split('_')[1])); 

Demo.

+0

正是!感谢你的付出! +1 – Oosutsuke

2

我想象任何数字排序首先需要将该值转换为数字类型。所以你可以分割下划线,按第一个值排序,然后按第二个值排序。事情是这样的:

list.OrderBy(x => x.Split('_')[0]).ThenBy(x => int.Parse(x.Split('_')[1])) 

你可以,如果有必要改善这一点,通过创建一个类承担其构造函数的字符串表示,提供的数字表示(与原来的字符串表示)作为属性。然后.Select()进入该类的列表并进行排序。这个类可以在内部做类型检查,范围检查等上面

+0

我明白。感谢你的付出! +1 – Oosutsuke

1

答案是更容易跟踪/理解,但纯粹作为学术兴趣选择,你可以做到以下几点:

var sorted = listStr.OrderBy(x => Convert.ToInt32(x.Split('_')[0])*100 + Convert.ToInt32(x.Split('_')[1])); 

它的工作原理是,下划线之后的后缀部分将小于100,并将字符串的两个元素转换为一个整数,并保留相对的“大小”,然后对其进行排序。

其他两种方法比较容易理解,但有一点我的替代方法是它只需要排序一次,所以会快一点(尽管我怀疑这对任何实际情况都很重要世界情景)。

+0

谢谢您的明确解释!我学到了另外一种方法。 +1 – Oosutsuke