2

我有一个可能看起来像这样的字符串:“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;
    }
4

4 回答 4

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);
    }

当然,您可能想要添加一些错误检查,但我会留给您。

于 2012-12-11T16:04:56.543 回答
3

这将产生想要的结果(部分基于@Tigran的错误答案):

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);
于 2012-12-11T16:05:36.477 回答
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());

哈哈 :)

于 2012-12-11T16:08:18.510 回答
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();

演示

于 2012-12-11T16:22:32.840 回答