我有以下方式的字符串: -
string[] things = new string[] { "1", "10", "2", "1_1", "2_1","3_1" };
所需的输出是:
"1",
"1_1",
"2",
"2_1",
"3_1",
"10",
如何使用LINQ实现这一目标?
答案 0 :(得分:5)
是的,您可以按_
拆分每个部分,并将第一个字符串部分转换为整数。在事后排序时,这将确保10
不在2
之前。然后在第二步中根据最后一个数字
string[] things = new string[] { "5_3", "5_2", "1", "10", "2", "1_1", "2_1", "1_2", "3_1" };
string[] ordered = things.OrderBy(x=>Convert.ToInt32(x.Split('_').First())).
ThenBy(x=>Convert.ToInt32(x.Split('_').Last())).ToArray();
输出:
编辑:以下是为了提供信息而documentation of ThenBy的链接;)
答案 1 :(得分:2)
这个怎么样?
string[] strings = new string[] { "1", "10", "2", "1_1", "2_1", "3_1" };
var ordered = from str in strings
let weight = double.Parse(str.Replace("_", CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator))
let pair = new { Weight = weight, OriginalString = str }
orderby pair.Weight
select pair.OriginalString;
答案 2 :(得分:2)
这将为您提供所需的输出:
string[] things = new string[] { "1", "10", "2", "1_1", "2_1", "3_1" };
var list = from row in things select Decimal.Parse(row.Replace("_",CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator));
list = list.OrderBy(d=> d).ToList();
var StringList = from row in list select row.ToString("0.#").Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, "_");
答案 3 :(得分:2)
您可以使用OrderBy的一个重载,它允许您创建自己的密钥,并可能指定您自己的比较器。看起来您希望将_
视为小数分隔符。
一个快速&脏的方法是用小数分隔符替换_
,例如:
var decSeparator=CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
var orderedThings=things.OrderBy(thing=>double.Parse( thing.Replace("_",decSeparator)) )
.ToArray();
这很快&脏,因为它假设_
只出现一次。如果_
多次出现,则替换的字符串将不是有效数字
答案 4 :(得分:1)
如果格式严格,您可以解析为Version
并按顺序排序:
string[] orderedThings = things
.Select(t => new { Thing = t, Numbers = (t + "_0").Split('_') })
.Where(x => x.Numbers.All(s => s.All(char.IsDigit)))
.Select(x => new { x.Thing, VersionStr = String.Join(".",x.Numbers.Take(4)) })
.OrderBy(x => new Version(x.VersionStr))
.ThenBy(x => x.Thing)
.Select(x => x.Thing)
.ToArray();
t + "_0"
技巧是必要的,以确保也可以解析单个数字。一个版本至少需要一个主要部分和一个部分。如果有超过4个令牌(主要,次要,构建和修订),这也“有效”。然后只有前4个用于初始化Version
实例。