【问题标题】:Split String to array and Sort Array将字符串拆分为数组并排序数组
【发布时间】:2017-08-08 06:35:21
【问题描述】:

我正在尝试对用逗号分隔的字符串进行排序。但它的行为不像预期的那样

var classes = "10,7,8,9";
Console.Write(string.Join(",", classes.Split(',').OrderBy(x => x)));
Console.ReadKey();

输出是

10,7,8,9

但我希望预期的输出是这样的:

7,8,9,10

类可以有一个部分。像 7a,7b

我想在一行代码中实现它。

【问题讨论】:

  • 我知道这可能根本不是一个解决方案,但是您现在不能重新排序 var classes 以便它们在拆分之前以正确的顺序出现,如果您曾经读取过动态数据,请改为在该查询上进行排序?
  • 先将数组的每个元素转换成整数,然后尝试排序
  • @Xariez 我正在从服务中读取数据,因此在从数据库查询时无法执行排序
  • @SPnL 类如 7a、7b 无法转换为 int
  • 为什么一定要在一行代码中实现?

标签: c# .net arrays linq sorting


【解决方案1】:

你可以像这样使用正则表达式

var classes = "10,7,8,9";
Regex number = new Regex(@"^\d+");
Console.Write(string.Join(",", classes.Split(',').OrderBy(x => Convert.ToInt32(number.Match(x).Value)).ThenBy(x => number.Replace(x, ""))));
Console.ReadKey();

【讨论】:

  • 正如我提到的,类可以有一个部分。像 7a,7b
  • 这里的数字是多少
  • @tabby 忘记写了!现在已经修复了
【解决方案2】:

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections;
namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var l = new List<string> { "1D", "25B", "30A", "9C" };
    l.Sort((b, a) =>
    {
        var x = int.Parse(Regex.Replace(a, "[^0-9]", ""));
        var y = int.Parse(Regex.Replace(b, "[^0-9]", ""));
        if (x != y) return y - x;
        return -1 * string.Compare(a, b);
    });

    foreach (var item in l) Console.WriteLine(item);

        }
    }
}

输出: 一维 9C 25B 30A

在线编译: http://rextester.com/CKKQK66159

【讨论】:

  • 我做了一个函数,我可以调用它在排序类后接受字符串并返回字符串
【解决方案3】:

使用以下using-directive:

using System.Text.RegularExpressions;

然后尝试以下方法:

var input = "7,7a,8,9a,9c,9d,10";
var sorted = from sp in input.Split(',')
             let reg = Regex.Match(sp, @"(?<num>[0-9]+)(?<char>[a-z]*)", RegexOptions.IgnoreCase | RegexOptions.Compiled)
             let number = int.Parse(reg.Groups["num"].ToString())
             orderby reg.Groups["char"].ToString() ascending // sort first by letter
             orderby number ascending // then by number
             select sp;
var result = string.Join(",", sorted);

Console.WriteLine(result);
//output (tested): 7,7a,8,9a,9c,9d,10

它使用正则表达式来确定输入字符串的数字和字母部分。 正则表达式模式使用命名组,如下所示:(?&lt;group_name&gt; regex_expr )


上面代码的时间复杂度为O(n log(n)),以防您担心大量数字。


More information about named Regex groups.
More information about LINQ.
... and about the orderby-clause.

【讨论】:

  • 这很复杂,但它也解决了我的问题,谢谢:)
  • 可以进一步降低代码复杂度,但我认为这样就足够了。很高兴听到它对您有所帮助。
【解决方案4】:

都在一条线上,也支持'4a'等

编辑:在测试时,1,2,111,3 之类的字符串将显示为111,1,2,3,因此可能不是您要查找的内容。

        string str = "1,2,3,4a,4b,5,6,4c";
        str.Split(',').OrderBy(x => x).ToList().ForEach(x=> Console.WriteLine(x));
        Console.ReadKey();

【讨论】:

    【解决方案5】:

    这是我的实现:

    IEnumerable<Tuple<string, string[]>> splittedItems =
        items.Select(i => new Tuple<string, string[]>(i, Regex.Split(i, "([0-9]+)")));
    
    List<string> orderedItems = splittedItems.OrderBy(t => Convert.ToInt16(t.Item2[1]))
        .ThenBy(t => t.Item2.Length > 1 ? t.Item2[2] : "1")
        .Select(t => t.Item1).ToList();
    
    1. 将输入拆分为数字和非数字字符
    2. 将拆分后的字符串与其父字符串一起存储
    3. 按编号排序
    4. 然后按非数字字符排序
    5. 排序后再次取父字符串

    结果类似于必填:{ "10", "7", "8b", "8a", "9" } 排序为{ "7", "8a", "8b", "9", "10" }

    【讨论】:

      【解决方案6】:

      您正在对字符串进行排序(按字母顺序),所以是的,“10”在“7”之前。

      我的解决方案将 "10,7b,8,7a,9b" 转换为 "7a,7b,8,9b,10" (首先按整数前缀排序,然后是子字符串本身)。

      解析字符串前缀的辅助方法:

      private static int IntPrefix(string s)
          => s
          .TakeWhile(ch => ch >= '0' && ch <= '9')
          .Aggregate(0, (a, c) => 10 * a + (c - '0'));
      

      按整数前缀排序子字符串,然后按字符串本身:

      classes.Split(',') // string[]
      .Select(s => new { s, i = IntPrefix(s) }) // IEnumerable<{ s: string, i: int }>
      .OrderBy(si => si.i) // IEnumerable<{ s: string, i: int }>
      .ThenBy(si => si.s) // IEnumerable<{ s: string, i: int }>
      .Select(si => si.s) // IEnumerable<string>
      

      一个班轮(string.Join):

      var result = string.Join(",", classes.Split(',').Select(s => new {s, i =  IntPrefix(s)}).OrderBy(si => si.i).ThenBy(si => si.s).Select(si => si.s));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多