我有以下列表:
1 2 3 10 20 三十 狗 猫 30Dog 30Cat
我希望对它进行排序,以便得到以下列表:
1 2 3 10 20 30 30Cat 30Dog Cat Dog
我怎样才能在C#中做到这一点?我基本上想根据以下规则对列表进行排序:
整数按升序排序。以整数开头的任何值都将根据该整数值进行排序。任何不以整数开头的值都按其字符串值排序。
答案 0 :(得分:2)
您可以将字符串预处理为部分,然后使用Linq:
var list = new List<string>{"1", "2", "3", "10", "20", "30", "Dog", "Cat", "30Dog", "30Cat"};
var regEx = new Regex(@"^\d+");
var sorted = list
.Select(x => new { text = x, intPart = regEx.Match(x).Value })
.Select(x => new { text = x.text, intPart = string.IsNullOrEmpty(x.intPart) ? int.MaxValue : int.Parse(x.intPart) })
.OrderBy(x => x.intPart)
.ThenBy(x => x.text)
.Select(x => x.text);
sorted.Dump();
答案 1 :(得分:1)
听起来像你想要实现自定义比较器,然后将该自定义比较器传递给排序方法。
戴夫比什的榜样很棒;但是你不想使用正则表达式,这是我把它放在一起的程序版本。 static void Main(string[] args)
{
IEnumerable<string> strings = new[] { "1", "2", "3", "10", "20", "30", "Dog", "Cat", "30Dog", "30Cat" };
strings = strings.OrderBy(s => s, new CustomComparer());
var joined = string.Join(" ", strings);
Console.WriteLine(joined);
Console.ReadLine();
}
public class CustomComparer : IComparer<string>
{
public int Compare(string s1, string s2)
{
int x, y;
bool xInt, yInt;
xInt = int.TryParse(s1, out x);
yInt = int.TryParse(s2, out y);
if (xInt && yInt)
return x.CompareTo(y);
if (xInt && !yInt)
{
if (this.SplitInt(s2, out y, out s2))
{
return x.CompareTo(y);
}
else
{
return -1;
}
}
if (!xInt && yInt)
{
if (this.SplitInt(s1, out x, out s1))
{
return y.CompareTo(x);
}
else
{
return 1;
}
}
return s1.CompareTo(s2);
}
private bool SplitInt(string sin, out int x, out string sout)
{
x = 0;
sout = null;
int i = -1;
bool isNumeric = false;
var numbers = Enumerable.Range(0, 10).Select(it => it.ToString());
var ie = sin.GetEnumerator();
while (ie.MoveNext() && numbers.Contains(ie.Current.ToString()))
{
isNumeric |= true;
++i;
}
if (isNumeric)
{
sout = sin.Substring(i + 1);
sin = sin.Substring(0, i + 1);
int.TryParse(sin, out x);
}
return false;
}
}
输出看起来像......
1 2 3 10 20 30 30Cat 30Dog Cat Dog