0

我有一个像

public class KeyNamePair
{
 public string Key {get;set;}

 public string Name{get;set;}
}

我的代码

List<KeyNamePair> list =new List<KeyNamePair>();

    list.Add("1", "Day 1");
    list.Add("2", "Day 11");
    list.Add("4", "Day 5");
    list.Add("6", "Day 13");

如何对列表进行排序以显示

>  "Day1", "Day5", "Day 11", "Day 13"

为了?

我试过了

var SortedList = source.OrderBy(x => x.Name).ToList();
            return SortedList;

这没有任何作用

4

7 回答 7

3

尝试类似:

var SortedList = source.OrderBy(x=>int.Parse(x.Name.Split(' ')[1])).ToList();
return SortedList;

如果数据是其他格式,它将不起作用,但它应该适用于您提供的格式。您不能按字符串本身排序,因为字符串“13”<“5”

于 2013-10-09T11:45:11.233 回答
2

有没有机会这样排序?

第 1 天 第 11 天 第 13 天 第 5 天

这将是我所期望的。OrderBy 有一个重载,允许您指定如何排序。正在发生的排序是字母数字排序,因此它是正确的。如果你这样做了...

第 1 天 第 11 天 第 13 天 第 5 天

你会看到它正确排序。

于 2013-10-09T11:44:49.950 回答
1

我们完全可以通过调用Windows API 函数来作弊,该函数StrCmpLogicalW()在两个字符串之间进行自然排序顺序比较。

然后我们可以使用内置的 List.Sort()。根本不需要涉及 Linq:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Demo
{
    class Program
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        private static extern int StrCmpLogicalW(string lhs, string rhs);

        private void run()
        {
            var list = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("1", "Day 1"), 
                new KeyValuePair<string, string>("2", "Day 11"), 
                new KeyValuePair<string, string>("4", "Day 5"),
                new KeyValuePair<string, string>("6", "Day 13")
            };

            list.Sort((lhs, rhs) => StrCmpLogicalW(lhs.Value, rhs.Value));

            foreach (var keyValuePair in list)
                Console.WriteLine(keyValuePair);
        }

        static void Main(string[] args)
        {
            new Program().run();
        }
    }
}

我假设您确实想按“值”而不是“键”排序,并且您遇到的问题是字符串编号没有按数字顺序排序。


编辑:应用 Jim Tollan 的想法,您可以创建一个扩展方法来隐藏 PInvoke,如下所示:

public static class ListExt
{
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int StrCmpLogicalW(string lhs, string rhs);

    // Version for lists of any type.
    public static void SortNatural<T>(this List<T> self, Func<T, string> stringSelector)
    {
        self.Sort((lhs, rhs) => StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs)));
    }

    // Simpler version for List<string>
    public static void SortNatural(this List<string> self)
    {
        self.Sort(StrCmpLogicalW);
    }
}

然后对列表进行排序的行将如下所示:

list.SortNatural(element => element.Value);
于 2013-10-09T12:26:04.530 回答
0

你有几个问题:

  1. 您正在尝试对将“第 1 天”和“第 11 天”计算为比“第 1 天”和“第 2 天”更匹配的 Name 属性进行排序
  2. 您可能会更好地对键进行排序(另外,如果键只包含数字值,我会将其设为数字​​,而不是字符串)。

这是我的修订:

public class KeyNamePair
{
    public int Key { get; set; }

    public string Name { get; set; }
}

List<KeyNamePair> list = new List<KeyNamePair>
    {
        new KeyNamePair() {Key = 1, Name = "Day 1"},
        new KeyNamePair() {Key = 4, Name = "Day 11"},
        new KeyNamePair() {Key = 2, Name = "Day 5"},
        new KeyNamePair() {Key = 6, Name = "Day 13"}
    };

var sortedList = list.Select(x => x).OrderBy(x => x.Key).ToList();

[编辑] - 我正在反思这样一个事实,即我觉得重构类的逻辑和它的人口会更好,而不是试图强制一些可能在文化特定实现上失败的任意顺序,如在这方面,字符串是出了名的脆弱。

于 2013-10-09T12:00:46.120 回答
0

我相信你会对此感到满意的:)

public class KeyNamePair : IComparable
{
  public string Key { get; set; }

  public string Name { get; set; }

  public KeyNamePair(string key, string name)
  {
    this.Key = key;
    this.Name = name;
  }

  public int CompareTo(object obj)
  {
    var tmp = (KeyNamePair)obj;
    var newKey = int.Parse(tmp.Name.Split(' ')[1]);

    var oldKey = int.Parse(Name.Split(' ')[1]);

    if (oldKey > newKey)
      return (1);
    if (oldKey < newKey)
      return (-1);
    else
      return (0);
  }
}

  List<KeyNamePair> list = new List<KeyNamePair>();

  list.Add(new KeyNamePair("1", "Day 1"));
  list.Add(new KeyNamePair("2", "Day 11"));
  list.Add(new KeyNamePair("4", "Day 5"));
  list.Add(new KeyNamePair("6", "Day 13"));
  list.Sort();

  foreach (var keyNamePair in list)
  {
    System.Console.Write(keyNamePair);
  }
于 2013-10-09T12:28:59.163 回答
0

我认为这不是一个好方法,但这项工作

list.OrderBy(x =>
     {
         return Int32.Parse(x.Name.Split(' ')[1]);
     });
于 2013-10-09T11:48:42.457 回答
0

这应该有效:

list = list.OrderBy(kn => {
    var digits = kn.Name.Split().Last();
    int num = int.MaxValue;
    if (digits.All(Char.IsDigit))
    { 
        num = int.Parse(new string(digits.ToArray()));
    }
    return num;
}).ToList();

旁注:您也可以使用已经可用的KeyValuePair<string, string>.

于 2013-10-09T11:46:26.707 回答