首先按字母数字值排序列表,然后按数字值排序

时间:2013-12-09 08:03:40

标签: c# linq

class ListSort
{
    static void Main(string[] args)
    {
        string[] partNumbers = new string[] 
        { 
           "India", "US","UK", "Australia","Germany", "1", "7", "9" 
        };
        var result = partNumbers.OrderBy(x => x).ToList();                    
    }
}

我尝试了上面的代码,并期望得到以下输出:

Australia
Germany
India
UK
US
1
7
9 

修改: 数字应按数字排序(1,7,9,70,...),而非数字应始终按词汇顺序排列,即使内部有数字(“A3stralia”,“Australia”,“Germany”)。

5 个答案:

答案 0 :(得分:1)

试试这个:

string[] partNumbers = new string[] 
  { 
    "India", "US","UK", "Australia","Germany", "1", "7", "9" 
  };

var result = partNumbers.OrderBy(x => char.IsNumber(x.FirstOrDefault())).ThenBy(x => x).ToList().Dump();

请注意,这仅适用于您的数据是数字或文本,而不是像“U2S”这样的值。如果你需要的话,我也可以改变它以适应这些情况。此外,数字字符串仍然按字符串排序,因此“10”出现在“2”之前。

A3stralia70添加到列表中时,您希望结果如何?

编辑:更改了新约束:

string[] partNumbers = new string[] 
  { 
      "India", "US","UK", "Australia","Germany", "1", "7", "9", "70", "A3stralia" 
  };

var result = 
    partNumbers
        .Select(x => { int p; bool isNumber = int.TryParse(x, out p);  return new { IsNumber = isNumber, NumericValue = isNumber ? p : int.MinValue, StringValue = x }; })
        .OrderBy(x => x.IsNumber)
        .ThenBy(x => x.NumericValue)
        .ThenBy(x => x.StringValue)
        .Select(x => x.StringValue)
        .ToList();

答案 1 :(得分:1)

如果按字典顺序排列数字部分无关紧要:

var result = partNumbers.OrderBy(s => s.All(Char.IsDigit)).ThenBy(s => s).ToList();   

这只是检查所有字符是否都是数字。如果您想要数字,请先使用Enumerable.OrderByDescending

如果你想要以数字方式订购数字的答案之一,那么你需要先解析它们:

result = partNumbers
  .Select(s => new { s, num = s.TryGetInt() } )
  .GroupBy(x => x.num.HasValue) // two groups: one can be parsed to int the other not 
  .SelectMany (xg =>
  {
      if (xg.Key) // can be parsed to int, then order by int-value
          return xg.OrderBy(x => x.num.Value).Select(x => x.s);
      else       // can not be parsed to int, order by the string
          return xg.OrderBy(x => x.s).Select(x => x.s);
  })
  .ToList();    

我正在使用此扩展程序在LINQ查询中解析stringsNullable<int>

public static class NumericExtensions
{   
    public static int? TryGetInt(this string item)
    {
        int i;
        bool success = int.TryParse(item, out i);
        return success ? (int?)i : (int?)null;
    }
}

答案 2 :(得分:1)

到目前为止,似乎所有的反应大致相同,但都太复杂了。我的尝试:

string[] partNumbers = { "US", "1", "UK", "Australia", "Germany", "70", "9" };
partNumbers.OrderBy(x =>
    { 
        int parseResult; 
        return int.TryParse(x, out parseResult) 
            ? parseResult 
            : null as int?; 
    }) 
    .ThenBy(x => x);

或者,使用提取的辅助方法:

partNumbers.OrderBy(TryParseNullableInt).ThenBy(x => x);

private static int? TryParseNullableInt(string source)
{
    int parseResult; 
    return int.TryParse(x, out parseResult) 
        ? parseResult 
        : null as int?;
}

答案 3 :(得分:0)

以下解决方案将字符串序列投影到匿名类型{ isNumber, s, value },其中包含序列中的当前项,信息是否为项是整数,以及可能的解析结果。然后将新序列分组为两组 - 一组用于数字,一组用于其他字符串。每个组都按照字母顺序排序 - 数字比较,字符串。并且从展平组中选择原始项目:

string[] partNumbers = { "US", "1", "UK", "Australia", "Germany", "70", "9" };
int value;
var result = partNumbers
    .Select(s => new { isNumber = Int32.TryParse(s, out value), s, value })
    .GroupBy(x => x.isNumber)
    .OrderBy(g => g.Key)
    .SelectMany(g => g.Key ? g.OrderBy(x => x.value) : g.OrderBy(x => x.s))
    .Select(x => x.s)
    .ToList();

返回:

"Australia",
"Germany",
"UK",
"US",
"1",
"9",
"70"

答案 4 :(得分:0)

    string[] partNumbers = new string[] 
                            { 
                                "India", "US","UK", "Australia","Germany", "1", "7", "9" 
                            };

    var result = partNumbers.OrderBy(x =>
                {
                    int i;
                    return int.TryParse(x, out i);
                }).ThenBy(x=>x);