如何使用 C# 对字符串进行排序
本文关键字:排序 字符串 何使用 | 更新日期: 2023-09-27 18:34:29
我有一个类似的类
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;
这不做任何排序
尝试类似操作:
var SortedList = source.OrderBy(x=>int.Parse(x.Name.Split(' ')[1])).ToList();
return SortedList;
如果数据采用其他格式,则它不起作用,但它应该适用于您提供的格式。不能按字符串本身排序,因为字符串"13"<"5">
它是否
偶然会这样排序?
第一天第11天第13天第五天
这将是我所期望的。OrderBy 上有一个重载,允许您指定如何排序。正在发生的排序是字母数字排序,因此它是正确的。如果你这样做了...
第01天第11天第13天第05天
你会看到它排序正确。
我们完全可以通过调用 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);
这应该有效:
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>
。
我认为这不是一个好方法,但这项工作
list.OrderBy(x =>
{
return Int32.Parse(x.Name.Split(' ')[1]);
});
你在这里遇到了一些问题:
- 您正在尝试对 Name 属性进行排序,该属性将"第 1 天"和"第 11 天"计为比"第 1 天"和"第 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();
[编辑] - 我正在反思这样一个事实,即我觉得重构类的逻辑和它的人口会更好,而不是试图共同处理一些可能在文化特定实现上失败的任意顺序,因为字符串在这方面是出了名的脆弱。
我相信你会对此感到满意:(
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);
}