转换列表号码范围字符串 [英] Convert list to number range string

查看:69
本文介绍了转换列表号码范围字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题是pretty这个问题很多相反的:
<一href=\"http://stackoverflow.com/questions/40161/does-c-have-built-in-support-for-parsing-page-number-strings\">Does C#有内置的解析页面数字符串支持?

因此​​,考虑

  1,3,5,6,7,8,9,10,12:

我将输出继电器:

  1,3,5-10,12

这是我第一次尝试。这似乎有点哈克,可能是最糟糕的code我曾经写道。您能否提供一个imporovement \\更好的方式来做到这一点?

 静态字符串numListToRangeStr(列表&LT; INT&GT; numList)
{
    StringBuilder的retString =新的StringBuilder();
    numList.Sort();    布尔inRangeFind = FALSE;
    INT firstInRange = numList [0];
    INT lastNumber = firstInRange;
    布尔第一= TRUE;    的for(int i = 1; I&LT; numList.Count;我++)
    {
        如果(numList [Ⅰ] ==(lastNumber + 1))
        {
            inRangeFind = TRUE;
        }
        其他
        {
            如果(inRangeFind)
            {
                如果(!第一)
                {
                    retString.Append(,);
                }
                retString.Append(firstInRange);
                retString.Append( - );
            }
            其他
            {
               如果(!第一)
                {
                    retString.Append(,);
                }
            }            retString.Append(lastNumber);            firstInRange = numList [I]
            inRangeFind = FALSE;
            第一= FALSE;
        }        lastNumber = numList [I]
    }
    如果(inRangeFind)
    {
        如果(!第一)
        {
            retString.Append(,);
        }
        retString.Append(firstInRange);
        retString.Append( - );
    }
    其他
    {
        如果(!第一)
        {
            retString.Append(,);
        }
    }
    retString.Append(lastNumber);    返回retString.ToString();
}


解决方案

在一些有几个可移动部件是这样,我觉得它有助于把它分解成小的逻辑单元,然后将它们结合在一起。小逻辑单元甚至可能是有用的分别。下面的code打破了问题分解成:


  • 转动异质组顺序和非顺序编号的成均匀组范围(可能包括简并范围这开始,并在同一号码结束)

  • 办法pretty打印这样的范围:(X,Y)打印为X-Y; (X,X)打印为X

  • 的方式来interperse可枚举的元件之间的分离器,并把结果转换成一个字符串。

该计划是:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;命名空间ConsoleApplication37 {
  公共静态类节目{
    静态无效的主要(字串[] args){
      变种numList =新[] {1,3,5,6,7,8,9,10,12};
      Console.WriteLine(numListToPossiblyDegenerateRanges(numList)。选择(R =&GT; prettyRange(R))中散布(,));
    }    ///&LT;总结&gt;
    例如/// 1,3,5,6,7,8,9,10,12
    ///变
    ///(1,1),(3,3),(5,10),(12,12)
    ///&LT; /总结&gt;
    公共静态的IEnumerable&LT元组LT; INT,INT&GT;&GT; numListToPossiblyDegenerateRanges(IEnumerable的&LT; INT&GT; numList){
      元组LT; INT,INT&GT; currentRange = NULL;
      的foreach(在numList VAR NUM){
        如果(currentRange == NULL){
          currentRange = Tuple.Create(NUM,NUM);
        }否则如果(currentRange.Item2 == NUM​​-1){
          currentRange = Tuple.Create(currentRange.Item1,NUM);
        }其他{
          产生回报currentRange;
          currentRange = Tuple.Create(NUM,NUM);
        }
      }
      如果(currentRange!= NULL){
        产生回报currentRange;
      }
    }    ///&LT;总结&gt;
    例如/// (1,1)变成1
    ///(1,3)变为1-3
    ///&LT; /总结&gt;
    ///&LT; PARAM NAME =范围&GT;&LT; /参数&GT;
    ///&LT;&回报GT;&LT; /回报&GT;
    公共静态字符串prettyRange(元组LT; INT,INT&GT;范围){
      如果(range.Item1 == range.Item2){
        返回range.Item1.ToString();
      }
      返回的String.Format({0} - {1},range.Item1,range.Item2);
    }    公共静态字符串中散布(这IEnumerable的&LT;串GT;的项目,串interspersand){
      变种currentInterspersand =;
      VAR的结果=新的StringBuilder();
      的foreach(在项目VAR项){
        result.Append(currentInterspersand);
        result.Append(项目);
        currentInterspersand = interspersand;
      }
      返回result.ToString();
    }
  }
}

This question is pretty much the opposite of this question: Does C# have built-in support for parsing page-number strings?

So given

1,3,5,6,7,8,9,10,12:

I will ouput:

1,3,5-10,12

Here is my first attempt. It seems kind of hacky and is probably the worst code I ever wrote. Can you suggest an imporovement\better way to do it?

static string numListToRangeStr(List<int> numList)
{
    StringBuilder retString = new StringBuilder();
    numList.Sort();

    bool inRangeFind = false;
    int firstInRange = numList[0];
    int lastNumber = firstInRange;
    bool first = true;

    for (int i = 1; i < numList.Count; i++)
    {
        if (numList[i] == (lastNumber + 1))
        {
            inRangeFind = true;
        }
        else
        {             
            if (inRangeFind)
            {
                if (!first)
                {
                    retString.Append(",");
                }
                retString.Append(firstInRange);
                retString.Append("-");
            }
            else
            {
               if (!first)
                {
                    retString.Append(",");
                }
            }

            retString.Append(lastNumber);

            firstInRange = numList[i];
            inRangeFind = false;
            first = false;
        }

        lastNumber = numList[i];
    }


    if (inRangeFind)
    {
        if (!first)
        {
            retString.Append(",");
        }
        retString.Append(firstInRange);
        retString.Append("-");
    }
    else
    {
        if (!first)
        {
            retString.Append(",");
        }
    }
    retString.Append(lastNumber);

    return retString.ToString();
}

解决方案

When something has several moving parts like this, I think it helps to decompose it into little logical units and then combine them together. The little logical units might even be usable separately. The code below breaks the problem down into:

  • turning the heterogeneous set of sequential and nonsequential numbers into a homogenous set of ranges (possibly including "degenerate" ranges which start and end at the same number)
  • a way to "pretty-print" such ranges: (x,y) prints as "x-y"; (x,x) prints as "x"
  • a way to interperse a separator between elements of an enumerable, and convert the result into a string.

The program is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication37 {
  public static class Program {
    static void Main(string[] args) {
      var numList=new[] {1, 3, 5, 6, 7, 8, 9, 10, 12};
      Console.WriteLine(numListToPossiblyDegenerateRanges(numList).Select(r => PrettyRange(r)).Intersperse(","));
    }

    /// <summary>
    /// e.g. 1,3,5,6,7,8,9,10,12
    /// becomes
    /// (1,1),(3,3),(5,10),(12,12)
    /// </summary>
    public static IEnumerable<Tuple<int,int>> numListToPossiblyDegenerateRanges(IEnumerable<int> numList) {
      Tuple<int, int> currentRange=null;
      foreach(var num in numList) {
        if(currentRange==null) {
          currentRange=Tuple.Create(num, num);
        } else if(currentRange.Item2==num-1) {
          currentRange=Tuple.Create(currentRange.Item1, num);
        } else {
          yield return currentRange;
          currentRange=Tuple.Create(num, num);
        }
      }
      if(currentRange!=null) {
        yield return currentRange;
      }
    }

    /// <summary>
    /// e.g. (1,1) becomes "1"
    /// (1,3) becomes "1-3"
    /// </summary>
    /// <param name="range"></param>
    /// <returns></returns>
    public static string PrettyRange(Tuple<int,int> range) {
      if(range.Item1==range.Item2) {
        return range.Item1.ToString();
      }
      return string.Format("{0}-{1}", range.Item1, range.Item2);
    }

    public static string Intersperse(this IEnumerable<string> items, string interspersand) {
      var currentInterspersand="";
      var result=new StringBuilder();
      foreach(var item in items) {
        result.Append(currentInterspersand);
        result.Append(item);
        currentInterspersand=interspersand;
      }
      return result.ToString();
    }
  }
}

这篇关于转换列表号码范围字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆