我有车牌号码,我返回到UI,我希望它们以asc顺序排序:
所以让我们说输入如下:
1/12/13/2
1/12/11/3
1/12/12/2
1/12/12/1
我的预期输出是:
1/12/11/3
1/12/12/1
1/12/12/2
1/12/13/2
我目前的代码是:
var orderedData = allLicenceNumbers
.OrderBy(x => x.LicenceNumber.Length)
.ThenBy(x => x.LicenceNumber)
.ToList();
但是对于另一个输入样本如下:
4/032/004/2
4/032/004/9
4/032/004/3/A
4/032/004/3/B
4/032/004/11
我将数据返回为:
4/032/004/2
4/032/004/9
4/032/004/11
4/032/004/3/A
4/032/004/3/B
当我需要的是:
4/032/004/2
4/032/004/3/A
4/032/004/3/B
4/032/004/9
4/032/004/11
我是否有更好的方法可以简单地在两个样本输入中给出正确的结果,或者我需要编写自定义排序?
修改
它不会总是字符串上的相同元素。
这可以是示例输入:
2/3/5/1/A
1/4/6/7
1/3/8/9/B
1/3/8/9/A
1/5/6/7
预期输出为:
1/3/8/9/A
1/3/8/9/B
1/4/6/7
1/5/6/7
2/3/5/1/A
答案 0 :(得分:3)
您应该拆分数字并将每个部分相互比较。按字典顺序比较数字和字符串。
var licenceNumbers = new[]
{
"4/032/004/2",
"4/032/004/9",
"4/032/004/3",
"4/032/004/3/A",
"4/032/004/3/B",
"4/032/004/11"
};
var ordered = licenceNumbers
.Select(n => n.Split(new[] { '/' }))
.OrderBy(t => t, new LicenceNumberComparer())
.Select(t => String.Join("/", t));
使用以下比较器:
public class LicenceNumberComparer: IComparer<string[]>
{
public int Compare(string[] a, string[] b)
{
var len = Math.Min(a.Length, b.Length);
for(var i = 0; i < len; i++)
{
var aIsNum = int.TryParse(a[i], out int aNum);
var bIsNum = int.TryParse(b[i], out int bNum);
if (aIsNum && bIsNum)
{
if (aNum != bNum)
{
return aNum - bNum;
}
}
else
{
var strCompare = String.Compare(a[i], b[i]);
if (strCompare != 0)
{
return strCompare;
}
}
}
return a.Length - b.Length;
}
}
答案 1 :(得分:1)
如果我们可以假设
4
,032
,004
,2
3
)4
,032
)或非数字(例如A
,B
)我们只能PadLeft
每个号码牌的数字部分0
,以便不比较"3"
和"11"
(并获得"3" > "11"
),但填充{ {1}}:
"003" < "011"
结果:
var source = new string[] {
"4/032/004/2",
"4/032/004/9",
"4/032/004/3/A",
"4/032/004/3/B",
"4/032/004/11",
};
var ordered = source
.OrderBy(item => string.Concat(item
.Split('/') // for each part
.Select(part => part.All(char.IsDigit) // we either
? part.PadLeft(3, '0') // Pad digit parts e.g. 3 -> 003, 11 -> 011
: part))); // ..or leave it as is
Console.WriteLine(string.Join(Environment.NewLine, ordered));
答案 2 :(得分:0)
您似乎想要在数字而不是字符串模式中对字符串的第四个元素(由/分隔)进行排序。?
你可以通过像{}
中的任何其他方法代码块那样使lambda更多参与/多语句var orderedData = allLicenceNumbers
.OrderBy(x =>
{
var t = x.Split('/');
if(t.Length<4)
return -1;
else{
int o = -1;
int.TryParse(t[3], out o);
return o;
}
)
.ToList();
如果您在对字符串的更多元素进行排序之后,您可能想要查看一些替代逻辑,也许如果字符串的第一部分将始终采用N / NNN / NNN / ?? / ?,然后执行:
var orderedData = allLicenceNumbers
.OrderBy(w => w.Remove(9)) //the first 9 are always in the form N/NNN/NNN
.ThenBy(x => //then there's maybe a number that should be parsed
{
var t = x.Split('/');
if(t.Length<4)
return -1;
else{
int o = -1;
int.TryParse(t[3], out o);
return o;
}
)
.ThenBy(y => y.Substring(y.LastIndexOf('/'))) //then there's maybe A or B..
.ToList();
最终,似乎越来越多的异常值将被投入到混合中,所以你只需要继续发明规则来排序......
或者更改你的字符串以标准化所有内容(例如,以NNN / NNN / NNN / NNN / NNA格式为单位),然后排序为字符串..
var orderedData = allLicenceNumbers
.OrderBy(x =>
{
var t = x.Split('/');
for(int i = 0; i < t.Length; i++) //make all elements in the form NNN
{
t[i] = "000" + t[i];
t[i] = t[i].Substring(t[i].Length - 3);
}
return string.Join(t, "/");
}
)
.ToList();
嗯......讨厌!