C#Linq复杂的顺序

时间:2017-06-09 11:42:29

标签: c# linq

我有一个字符串列表,如: -

  

" 008"," a"," 007"," b"," c",&# 34; 009"

需要OutPut: -

  

" a"," b"," c"," 007"," 008",&# 34; 009"   到目前为止我尝试了什么

string[] things= new string[] {  "aaul", "bob", "lauren", "007", "008", "009"};



foreach (var thing in things.AsQueryable().OrderByDescending(x => x, new SemiNumericComparer()))
{    
    Console.WriteLine(thing);
}

public class SemiNumericComparer: IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (IsNumeric(s1) && IsNumeric(s2))
        {
             if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 0;
            if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return 1;
            if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return -1;
        }

        if (IsNumeric(s1) && !IsNumeric(s2)){
            return -1;
        }

        if (!IsNumeric(s1) && IsNumeric(s2)){
            return 1;

        };
        return string.Compare(s1, s2, true);
    }

    public static bool IsNumeric(object value)
    {
        try {
            int i = Convert.ToInt32(value.ToString());
            return true; 
        }
        catch (FormatException) {
            return false;
        }
    }
}

I Already tried

Here is problem fiddle using above solution

我能够获得像

这样的输出
  

a,b,c,009,008,007或007,008,009,c,b,a但需要a,b,c,007,008,009任何想法?

7 个答案:

答案 0 :(得分:4)

你想订购两个组,首先是那些不是整数然后是整数的组。第一组按字典顺序排序,而数字按其值排序?

我使用下面的扩展方法try-parses string to int:

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

然后您可以使用此LINQ查询来获得所需的顺序:

string[] things = new string[] { "008", "bob", "009", "007", "aaul", "lauren" };

var ordered = things
    .Select(s => new { s, numberOrNull = s.TryGetInt() }) // store in anonymous type
    .OrderBy(x => x.numberOrNull.HasValue ? 1 : 0)        // first non-integer group
    .ThenBy(x => x.numberOrNull.HasValue ? x.numberOrNull.Value : int.MinValue) // then by number value
    .ThenBy(x => x.s)  // if they weren't numbers order lexicographically
    .Select(x => x.s); // select the string

答案 1 :(得分:2)

首先将不同的起始字母组(数字或非数字)分开,然后对每个组进行排序

things.OrderBy(x => char.IsDigit(x.FirstOrDefault())).ThenBy(x => x)

答案 2 :(得分:2)

public class SemiNumericComparer: IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (IsNumeric(s1) && IsNumeric(s2))
        {
            if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1;
            if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1;
            if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0;
        }

        if (IsNumeric(s1) && !IsNumeric(s2))
            return 1;

        if (!IsNumeric(s1) && IsNumeric(s2))
            return -1;

        return string.Compare(s1, s2, true);
    }

    public static bool IsNumeric(object value)
    {
        try {
            int i = Convert.ToInt32(value.ToString());
            return true; 
        }
        catch (FormatException) {
            return false;
        }
    }
}

取自here并将其修改为先排序字母

使用OrderBy代替OrderByDescending

答案 3 :(得分:2)

首先按int / not int排序,然后按内容

排序
string[] things = new string[] { "a", "b", "c", "009", "008", "007" };
int temp=0;
string[] result = things.OrderBy(x => int.TryParse(x, out temp))
                        .ThenBy(x => x)
                        .ToArray();

更新到蒂姆的评论(natural order int值和lexicographical strings

string[] things = new string[] { "c", "b", "a", "009", "008", "007" , "1234", "299" };
int temp = 0;
string[] result = things.OrderBy(x => int.TryParse(x, out temp) ? temp : int.MinValue)
                        .ThenBy(x => x)
                        .ToArray();

答案 4 :(得分:2)

使用Regex尝试以下内容:

string[] str = { "008", "abhi", "007", "bcd", "cde", "009" };
str = str.OrderBy(x => Regex.IsMatch(x, @"^\d+$")).ThenBy(x => x).ToArray<string>();

答案 5 :(得分:2)

你做错了是Compare方法的实施。

仔细查看文档:

  

返回值

     

有符号整数,表示x和y的相对值,如下表所示。

Value                 Meaning
Less than zero        x is less than y.
Zero                  x equals y.
Greater than zero     x is greater than y.

你正在返回它应该在&#34中的反向;两个字符串都是数字&#34;案件。只需切换它就可以了:

 if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1;
if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1;
if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0;

答案 6 :(得分:1)

试试这个:

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        int i1, i2;
        bool b1 = int.TryParse(s1, out i1);
        bool b2 = int.TryParse(s2, out i2);
        if (b1 && b2)
        {
            return i1.CompareTo(i2);
        }
        if (b1) return 1;
        if (b2) return -1;
        return string.Compare(s1, s2, true);
    }
}