C#LINQ OrderBy具有条件整数的字符串

时间:2016-12-11 08:43:25

标签: c# string linq sorting

请帮我处理字符串排序。

我有一个List,其中包含Oracle数据库select语句的结果。一般来说,它看起来像这样:

"9",
"10 k. 1 str. 1",
"10 k. 2 str. 1",
"11 k.1",
"12",
"12 k.1 str. 2"

但当然没那么好。

我可以使用LINQ查询对其进行排序,例如:

var oLst = lst.OrderBy(x => int.Parse(x.Split(' ')[0])).ToList();

它对此列表进行排序,但仅限于第一个整数。我想做的是某种"条件的ThenBy()"基于x.Split(' ')[2]字符串元素的存在进行排序,但我无法弄清楚如何进行排序。我想要的是先排序"首先"字符串中的整数,如果它们存在 - 由第二个,然后是第三个。

var oLst = lst.OrderBy(x => int.Parse(x.Split(' ')[0])).ThenBy(x => int.Parse(x.Split(' ')[2])).ThenBy(x => int.Parse(x.Split(' ').Last())).ToList();

仅适用于"完整字符串"它具有所有整数值,但如何在列表的某些字符串中不存在此Split(' ')[]元素的情况下管理这种情况?

4 个答案:

答案 0 :(得分:1)

您可以实现比较器:

public class NumberExtractorComparer : IComparer<MatchCollection>
{
    private static readonly Regex rx = new Regex("[0-9]+");

    public static readonly NumberExtractorComparer Comparer = new NumberExtractorComparer();

    // Returns a MatchCollection composed of all the groups of
    // digits
    public static MatchCollection Selector(string str)
    {
        return rx.Matches(str);
    }

    // Compares two matchcollections
    public int Compare(MatchCollection x, MatchCollection y)
    {
        int min = Math.Min(x.Count, y.Count);

        for (int i = 0; i < min; i++)
        {
            // Using long to support bigger numbers
            long l1 = long.Parse(x[i].Value);
            long l2 = long.Parse(y[i].Value);

            int cmp = l1.CompareTo(l2);

            if (cmp != 0)
            {
                return cmp;
            }
        }

        return x.Count.CompareTo(y.Count);
    }
}

然后

var res = lst
    .OrderBy(
        NumberExtractorComparer.Selector, 
        NumberExtractorComparer.Comparer)
    .ToArray();

请注意,我在进行比较之前(NumberExtractorComparer.Selector)正在提取数字(NumberExtractorComparer.Comparer)。这样,对于集合的每个元素,数字将只被提取一次(与比较部分相比,数字提取可能非常慢)

答案 1 :(得分:0)

您可以从字符串中提取数字并按数字值排序。

var oLst = lst.OrderBy(x => int.Parse(Regex.Replace(x, "[^0-9]", ""))).ToList();

答案 2 :(得分:0)

您可以将字符串转换为double,然后按该double进行排序。例如:

"9" => 9.0
"10 k. 1 str. 1" => 10.11
"10 k. 2 str. 1" => 10.21
"11 k.1" => 11.0
"12" => 12.0
"12 k.1 str. 2 => 12.2

实现这一诀窍的方法是:

Parse(string str)
        {
            double res = 0;
            string[] p = str.Split(' ');

            double multuplier = 1.0;

            p.ToList().ForEach(f =>
            {
                int parsed;
                if(int.TryParse(f, out parsed))
                {
                    res += parsed * multuplier;
                    multuplier *= 0.1;
                }
            });

            return res;
        }

然后只使用:

List<string> ordered = lst.OrderBy(Parse).ToList();

答案 3 :(得分:0)

var query = from x in source
  let tokens = x.Split(' ')
  order by
    GentlyParse(tokens.FirstOrDefault()),
    GentlyParse(tokens.Skip(2).FirstOrDefault()),
    GentlyParse(tokens.LastOrDefault())
  select x;

var results = query.ToList();

GentlyParse是一个你需要编写的方法,它接受一个字符串(或null)并返回可以解析的int或null。