如何根据每个索引中每个字符串中的数字对List <string>进行排序?</string>

时间:2014-07-27 15:54:10

标签: c# .net

最后在threadList中,例如在索引0中,我有:

1. hello world

然后在索引2中我有:

33. hello

然后在索引3中我有:

76. hi

在索引4中:

2. good

数字1 33 76 2是每个索引中字符串的一部分。

1. hello world是一个字符串。 我想根据数字对List进行排序,所以在这个例子中它应该是:

1. hello world
2. good
33. hello
76. hi

再次,数字是字符串的一部分,它们不是int。

这是创建List的方法:

public string GetResponsers(string contents)
        {
            string responser = "";
            List<string> threadList = new List<string>();
            int f = 0;
            int startPos = 0;
            while (true)
            {
                string firstTag = "<FONT CLASS='text16b'>";
                string lastTag = "&n";
                f = contents.IndexOf(firstTag, startPos);
                if (f == -1)
                {
                    break;
                }
                int g = contents.IndexOf(lastTag, f);
                startPos = g + lastTag.Length;
                responser = contents.Substring(f + 22, g - f - 22);

                threadList.Add(responser);
            }
            return responser;
        }

4 个答案:

答案 0 :(得分:3)

我想我明白了你想要的......

yourList.OrderBy(str => {
    var match = Regex.Match(str, @"^([-+]?\d+)");
    return match.Success ? int.Parse(match.Groups[1].Value) : int.MaxValue;
});

这将返回按字符串开头出现的整数值排序的IEnumerable<string>。没有编号的参赛作品将放在最后。


编辑:如果您想要订购变量yourList,那么您必须重新分配它:

yourList = yourList
    .OrderBy(str => {
        var match = Regex.Match(str, @"^([-+]?\d+)");
        return match.Success ? int.Parse(match.Groups[1].Value) : int.MaxValue;
    })
    .ToList();

答案 1 :(得分:0)

如果我再说一遍如果列表中的示例我将呈现给您的格式与您相同,那么您只需应用自动排序的排序方法:

            List<string> lst = new List<string>()
            {
                "1. hello world",
                "76. hi",
                "33. hello",
                "2. good"
            };

            lst.Sort();//this will sort the list

在此之后,列表将具有您想要的输出。

编辑: 正如所指出的那样(并且确实非常正确)我忘记了那些例如在这种情况下存在19的情况应用排序与比较:

     lst.Sort((s1, s2) =>
     {
          string first = new string(s1.TakeWhile(c => char.IsDigit(c)).ToArray());
          string second = new string(s2.TakeWhile(c => char.IsDigit(c)).ToArray());
          return int.Parse(first).CompareTo(int.Parse(second));
     });

答案 2 :(得分:0)

我想你也可以尝试这样的事情:

yourList.OrderBy(s => {
    int num;
    var parts = string.Split(s, '.');
    if (parts.Count > 0 && int.TryParse(parts[0], out num))
        return num;

    return int.MaxValue;
});

通过这种方式,您可以确保字符串数字部分的数字排序而不使用正则表达式。

答案 3 :(得分:0)

如果您使用的是Windows 7或更高版本,则它具有您可以P / Invoke进入的CompareStringEx功能。它的SORT_DIGITSASNUMBERS选项完全符合您的要求:

    static int CompareCSEx(string x, string y)
    {
        return CompareStringEx("", SORT_DIGITSASNUMBERS, x, x.Length,
                               y, y.Length, null, null, IntPtr.Zero) - 2;
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern int CompareStringEx(String strLocale, uint flags,
                                      String str1, int count1, string str2,
                                      int count2, string version,
                                      string reserved, IntPtr param);

    const int SORT_DIGITSASNUMBERS = 8;

请注意,这会将字符串中的所有数字视为数字,而不仅仅是字符串开头的数字。

而现在这个愚蠢的基准测试显示它运行速度比四个午夜的解决方案快了近4倍:

static void Main(string[] args)
{
    Random r = new Random(0);

    string[] values = (from i in Enumerable.Range(1, 500)
                        let order = r.Next()
                        orderby order
                        select i.ToString(CultureInfo.InvariantCulture)
                                    + ". " + RandomString(r)).ToArray();

    string[] fpmValues = values.ToArray();
    string[] csexValues = values.ToArray();

    Benchmark("FPM ", () => Array.Sort(fpmValues,
        new Comparison<string>(CompareFpm)));

    Benchmark("CSEX", () => Array.Sort(csexValues,
        new Comparison<string>(CompareCSEx)));

    Console.WriteLine("Sort equal: {0}",
        Enumerable.SequenceEqual(fpmValues, csexValues));
}

static string RandomString(Random r)
{
    int len = r.Next(1, 32);
    char[] buf = new char[len];

    for (int i = 0; i < len; ++i)
    {
        buf[i] = (char)r.Next('A', 'Z');
    }

    return new string(buf);
}

static int CompareFpm(string x, string y)
{
    int xi, yi;

    var parts = x.Split('.');
    if(parts.Length == 0 || !int.TryParse(parts[0], out xi))
    {
        xi = int.MaxValue;
    }

    parts = y.Split('.');
    if (parts.Length == 0 || !int.TryParse(parts[0], out yi))
    {
        yi = int.MaxValue;
    }

    return xi - yi;
}

static void Benchmark(string name, Action a)
{
    long start = Stopwatch.GetTimestamp(), end;
    long runs = 0;

    do
    {
        a();
        ++runs;
        end = Stopwatch.GetTimestamp();
    }
    while ((end - start) < (Stopwatch.Frequency * 5));

    Console.WriteLine("{0}: {1} runs/sec", name, runs / 5);
}

输出:

FPM : 681 runs/sec
CSEX: 2577 runs/sec
Sort equal: True