C# 顺序字符串式数字
我想对有时包含数值的字符串列表进行排序 我的清单如下:C# 顺序字符串式数字,c#,linq,C#,Linq,我想对有时包含数值的字符串列表进行排序 我的清单如下: 1号卧室 卧室2 10号卧室 浴室1 浴室2 10号浴室 1灯 1份文件 如果我只使用orderby: roomList.OrderBy(x=>x.Name) 我得到以下列表: 1灯 1份文件 浴室1 10号浴室 浴室2 1号卧室 10号卧室 卧室2 有可能得到这样的列表吗 1灯 1份文件 浴室1 浴室2 10号浴室 1号卧室 卧室2 10号卧室 所有列表元素都不包含数字,列表大约有1500行长 我尝试过使用这段代码,它在包含n
- 1号卧室
- 卧室2
- 10号卧室
- 浴室1
- 浴室2
- 10号浴室
- 1灯
- 1份文件
- 1灯
- 1份文件
- 浴室1
- 10号浴室
- 浴室2
- 1号卧室
- 10号卧室
- 卧室2
- 1灯
- 1份文件
- 浴室1
- 浴室2
- 10号浴室
- 1号卧室
- 卧室2
- 10号卧室
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;
}
}
}
公共类SemiNumericComparer:IComparer
{
公共整数比较(字符串s1、字符串s2)
{
if(IsNumeric(s1)和&IsNumeric(s2))
{
if(Convert.ToInt32(s1)>Convert.ToInt32(s2))返回1;
if(Convert.ToInt32(s1)
您正在寻找一种“自然排序”算法
例如:
尝试以下自定义IComparable:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication107
{
class Program
{
static void Main(string[] args)
{
List<string> input = new List<string>() { "1 Light", "1 Paper", "Bathroom 1", "Bathroom 2", "Bathroom 10", "Bedroom 1", "Bedroom 2", "Bedroom 10" };
List<string> results = input.Select(x => new { s = x, order = new Order(x) }).OrderBy(x => x.order).Select(x => x.s).ToList();
}
}
public class Order : IComparable<Order>
{
List<string> split { get; set; }
public Order(string line)
{
split = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
public int CompareTo(Order other)
{
int min = Math.Min(split.Count, other.split.Count);
int thisNumber = 0;
int otherNumber = 0;
for (int i = 0; i < min; i++)
{
if (split[i] != other.split[i])
{
if ((int.TryParse(split[i], out thisNumber)))
{
if ((int.TryParse(other.split[i], out otherNumber)))
{
return thisNumber.CompareTo(otherNumber); //both numbers
}
else
{
return -1; // this is number other is string : this comes first
}
}
else
{
if ((int.TryParse(other.split[i], out otherNumber)))
{
return 1; //other is number this is string : other comes first
}
else
{
return split[i].CompareTo(other.split[i]);
}
}
}
}
return split.Count.CompareTo(other.split.Count);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
命名空间控制台应用程序107
{
班级计划
{
静态void Main(字符串[]参数)
{
列表输入=新列表(){“1灯”、“1纸”、“浴室1”、“浴室2”、“浴室10”、“卧室1”、“卧室2”、“卧室10”};
List results=input.Select(x=>new{s=x,order=neworder(x)}).OrderBy(x=>x.order).Select(x=>x.s).ToList();
}
}
公共类秩序:IComparable
{
列表拆分{get;set;}
公共秩序(字符串行)
{
split=line.split(新字符[]{''},StringSplitOptions.removeMptyEntries.ToList();
}
公共整数比较(订购其他)
{
int min=Math.min(split.Count,other.split.Count);
int thisNumber=0;
int otherNumber=0;
对于(int i=0;i
您希望“2灯”和“10灯”的效果如何?“浴室蓝”怎么样?我不确定这是否适合您,但您可以编辑字符串,使其具有前导零<代码>浴室001,浴室002
,等等。或者,在运行时将数字部分转换为该格式,然后进行排序。两者在“边缘案例”场景中的工作方式应该有所不同。如果您有问题,请在您的数据上尝试一个,具体到案例中。但我很确定,如果它不是一个完全任意的规则,那么它要么是一个复制,要么是一个内置函数。自从我们开始使用计算机以来,人类一直在要求按顺序排列物品清单。我希望开发人员能在第二天找到一个简单的解决方案。这只适用于Windows环境。此外,如果可以(轻松地)避免引用内核dll,我也不建议引用它。除了@discy提到的内容之外,值得注意的是,strmplogical在不同的Windows版本上的行为可能会有所不同(这可能是可取的,也可能不是可取的,这取决于排序是否应与运行程序的Windows版本的排序行为相匹配)。
List<string> str = new List<string>
{
"Bedroom 1",
"Bedroom 2",
"Bedroom 10",
"Bathroom 1",
"Bathroom 2",
"Bathroom 10",
"1 Light",
"1 Paper"
};
str = str.OrderBy(x => x, new StringComparer()).ToList();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication107
{
class Program
{
static void Main(string[] args)
{
List<string> input = new List<string>() { "1 Light", "1 Paper", "Bathroom 1", "Bathroom 2", "Bathroom 10", "Bedroom 1", "Bedroom 2", "Bedroom 10" };
List<string> results = input.Select(x => new { s = x, order = new Order(x) }).OrderBy(x => x.order).Select(x => x.s).ToList();
}
}
public class Order : IComparable<Order>
{
List<string> split { get; set; }
public Order(string line)
{
split = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
public int CompareTo(Order other)
{
int min = Math.Min(split.Count, other.split.Count);
int thisNumber = 0;
int otherNumber = 0;
for (int i = 0; i < min; i++)
{
if (split[i] != other.split[i])
{
if ((int.TryParse(split[i], out thisNumber)))
{
if ((int.TryParse(other.split[i], out otherNumber)))
{
return thisNumber.CompareTo(otherNumber); //both numbers
}
else
{
return -1; // this is number other is string : this comes first
}
}
else
{
if ((int.TryParse(other.split[i], out otherNumber)))
{
return 1; //other is number this is string : other comes first
}
else
{
return split[i].CompareTo(other.split[i]);
}
}
}
}
return split.Count.CompareTo(other.split.Count);
}
}
}