我有一个字符串可能看起来像这样:“3,7,12-14,1,5-6”
我需要做的是将其更改为如下所示的字符串:“1,3,5,6,7,12,13,14”
我已经使下面的代码工作了,但我非常感谢帮助如何以更少的代码行更清洁地执行此操作:
private string sortLanes(string lanesString)
{
List<string> sortedLanes = new List<string>();
if (lanesString.Contains(',') || lanesString.Contains('-'))
{
List<string> laneParts = lanesString.Split(',').ToList();
foreach (string lanePart in laneParts)
{
if (lanePart.Contains('-'))
{
int splitIndex = lanePart.IndexOf('-');
int lanePartLength = lanePart.Length;
int firstLane = Convert.ToInt32(lanePart.Substring(0, splitIndex));
int lastLane = Convert.ToInt32(lanePart.Substring(splitIndex + 1, lanePartLength - splitIndex - 1));
while (firstLane != lastLane)
{
sortedLanes.Add(firstLane.ToString().Trim());
firstLane++;
}
sortedLanes.Add(lastLane.ToString());
}
else
{
sortedLanes.Add(lanePart.Trim());
}
}
sortedLanes.Sort();
sortedLanes = sortedLanes.OrderBy(x => x.Length).ToList();
lanesString = "";
foreach (string lane in sortedLanes)
{
if (lanesString.Length == 0)
{
lanesString = lane;
}
else
{
lanesString = lanesString + ", " + lane;
}
}
}
else
{
return lanesString;
}
return lanesString;
}
答案 0 :(得分:5)
我首先按,
拆分,然后将每个值转换为单个整数或所需范围。获取结果并重新排序,然后连接回字符串。这样的事情。
string test = "3, 7, 12-14, 1, 5-6";
var items = test.Split(',');
var ints = items.SelectMany(item => Expand(item));
string result = string.Join(", ", ints.OrderBy(i => i).ToArray());
private static IEnumerable<int> Expand(string str)
{
if (str.Contains('-'))
{
var range = str.Split('-');
int begin = int.Parse(range[0]);
int end = int.Parse(range[1]);
for (int i = begin; i <= end; i++)
yield return i;
}
else
yield return int.Parse(str);
}
当然你可能想要添加一些错误检查,但我会把它留给你。
答案 1 :(得分:3)
这将产生想要的结果(部分基于@Tigran的incorrect answer):
var parts = "3, 7, 12-14, 1, 5-6".Split(new string[] {", "}, StringSplitOptions.None).ToList();
var finalResult = new List<int>();
foreach(var item in parts)
{
if(item.Contains("-"))
{
var rangeParts = item.Split('-');
var first = int.Parse(rangeParts[0]);
var second = int.Parse(rangeParts[1]);
var result = Enumerable.Range(first, second - first + 1);
finalResult.AddRange(result);
}
else
{
finalResult.Add(int.Parse(item));
}
}
var sorted = finalResult.OrderBy(i => i);
var resultString = string.Join(", ", sorted);
答案 2 :(得分:0)
正则表达式在这里工作得很好......
static void Main()
{
Assert.AreEqual("1, 3, 5, 6, 7, 12, 13, 14", Transform("3, 7, 12-14, 1, 5-6"));
}
private static string Transform(string input)
{
StringBuilder sb = new StringBuilder();
foreach(Match m in new Regex(@"(?<start>\d+)(?:-(?<end>\d+))?(?:,|$)\s*").Matches(input)
.OfType<Match>().OrderBy(m => int.Parse(m.Groups["start"].Value)))
{
int start = int.Parse(m.Groups["start"].Value);
int end = !m.Groups["end"].Success ? start : int.Parse(m.Groups["end"].Value);
foreach (int val in Enumerable.Range(start, end - start + 1))
sb.AppendFormat("{0}, ", val);
}
if (sb.Length > 0)
sb.Length = sb.Length - 2;//remove trailing comma+space;
return sb.ToString();
}
<强>更新强>
如果我想让它变得混乱,我只需要使用一行代码:
return String.Join(", ",new Regex(@"(?<start>\d+)(?:-(?<end>\d+))?(?:,|$)\s*").Matches(input)
.OfType<Match>().OrderBy(m => int.Parse(m.Groups["start"].Value)).SelectMany(m =>
Enumerable.Range(int.Parse(m.Groups["start"].Value), int.Parse(m.Groups["end"].Success
? m.Groups["end"].Value : m.Groups["start"].Value) - int.Parse(m.Groups["start"].Value) + 1))
.Select(i => i.ToString()).ToArray());
LoL:)
答案 3 :(得分:0)
如果你喜欢Linq:
string input = "3, 7, 12-14, 1, 5-6";
List<int> all = input.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(r => new
{
Range = r,
Parts = r.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => int.Parse(p))
})
.SelectMany(x => Enumerable.Range(x.Parts.First(), 1 + x.Parts.Last() - x.Parts.First()))
.ToList();