【问题标题】:How to "summarize" an array of integers to a string with ranges?如何将整数数组“汇总”为具有范围的字符串?
【发布时间】:2015-09-16 13:45:25
【问题描述】:

假设您输入了Array=[1,2,3,5,7,9,10,11,12,15]

输出应该是1-3,5,7,9-12,15

我正在寻找有关我的尝试和其他可能解决方案的反馈。 这是我在 javascript 中的尝试:

var min = 0;
var max = -1;

function summarize(array) {
    var sumString = "";
    var prevVal = -1;

    array.forEach(function(currVal, index) {
        if (index > 0) {
            prevVal = array[index - 1];
        }
        if (index === 0) {
            min = currVal;
            max = currVal;
        } else if (currVal - prevVal === 1) {
            max = currVal;
        } else if (min !== max && max !== -1) {
            sumString += min + "-" + max + (index < array.length - 1 ? "," : "");
            min = currVal;
            max = -1;
        } else {
            sumString += min + (index < array.length - 1 ? "," : "");
        }

        if (index === array.length - 1) {
            if (max === -1) {
                sumString += "," + min;
            } else {
                sumString += min + "-" + max;
            }
        }
    });
    return sumString;
}

【问题讨论】:

标签: javascript arrays algorithm


【解决方案1】:

这是一个稍微短一点的实现:

var i = 0, prev, arr = [1,2,3,5,7,9,10,11,12,15], out = [];
for(i=0; i<arr.length; prev = arr[i], i++) {

    // if the current number is not prev+1, append it to out
    // Note that we are adding it as a string, to ensure that 
    // subsequent calls to `split()` (see else part) works
    if(prev !== arr[i] - 1) out.push(String(arr[i]));

    // if the current number is prev+1, modify the last value
    // in out to reflect it in the RHS of - (hyphen)
    else out[out.length - 1] = [out[out.length - 1].split('-')[0], String(arr[i])].join('-');
}

// out => ["1-3", "5", "7", "9-12", "15"]

【讨论】:

  • 很好,你能解释一下else中发生了什么吗?
  • @FuzzyTree - 添加了 cmets 解释 ifelse 部分中正在执行的操作。
  • 你能解释一下 prev-arr[i] 在 for 循环中是如何工作的吗?当我这样做时for(var i = 0; i &lt;10; prev = arr[i], i++) {console.log(i); console.log(prev)}。当 i 为 0 时,它记录未定义。
  • @DanielKobe - for 循环中的最后一部分(在本例中为 prev = arr[i], i++),在每次迭代之后执行。因此,当 i 为 0 时,即第一次迭代时,prev 没有分配给它的值,因此是 undefined。一旦 i 变为 1,prev 将变为 arr[0],以此类推。
【解决方案2】:

正数升序的另一种可能解决方案。它具有Array.prototype.reduce

var array = [1, 2, 3, 5, 7, 9, 10, 11, 12, 15, 23, 24],
    result = [];

array.reduce(function (r, a) {			
    result.push(r + 1 - a ? String(a) : result.pop().split('-')[0] + '-' + String(a));
    return a;
}, array[0]);		
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

【讨论】:

  • 问题。 1. 使用 reduce 与 forEach 有什么好处? 2. 你提供给 stringify 的参数是做什么的?
  • to 1:在forEach中,array[i-1]的前一个值没有参数。到 2:stringify 在值旁边有一个替换器和一个间隔器参数。我只使用 spacer 参数,它提供 4 个空格缩进。
【解决方案3】:

另一种可能的解决方案:

var points = [1,2,3,5,6,31,7,9,10,11,12,15];
points.sort(function(a, b){return a-b}); //sort array in asc
var resultArr=[];
var max; var min;
for(i=0;i<points.length;i++) //loop
{
    if(i==0)
    {
        min=points[i]; //lowest number in arr
        max=points[i]+1; //assign next value
    }
    else
    {
        if(max==points[i]) //if value matches continue
            max=points[i]+1;
        else //next value is not an incremental one so push it to result arr
        {
            max=max-1;
            resultArr.push(min+(min!=max? "-"+ max :""));
            min=points[i];
            max=points[i]+1;
        }
        if(i==points.length-1) //last element of the arr so push it to result arr
        {
            max=max-1;
            resultArr.push(min+(min!=max? "-"+ max :""));
        }

     }
}
alert(resultArr);

【讨论】:

    【解决方案4】:

    第一步使用破折号分隔序列号,如果不是,则使用逗号分隔。第二步将-#-替换为-

    var X = [1,2,3,5,7,9,10,11,12,15];
    var S = '' + X[0];
    for (var i = 1; i < X.length; i++) {
        S += (X[i] == X[i - 1] + 1)? '-': ',';
        S += X[i];
    }
    while (/-[0-9]+-/.test(S))
        S = S.replace(/-[0-9]+-/g, '-');
    alert(S);
    

    对于像1,2,5,6 这样的序列将输出1-2,5-6,这可能不是您要查找的内容,因此可选的第三步是将#-#+1 替换为#,#+1,即恢复逗号:

    for (var i = 1; i < X.length; i++)
        S = S.replace(X[i - 1] + '-' + X[i], X[i - 1] + ',' + X[i]);
    

    【讨论】:

      【解决方案5】:

      我最近遇到了这个问题,经过一番思考,我注意到了3种不同的转换:(1)分组连续数字; (2) 将组转换为表示范围的字符串; (3) 用逗号连接范围字符串。

      function summarizeRange(items) {
        const sorted = items.slice(0).sort((a, b) => a - b);
      
        return sorted
          .slice(1)
          .reduce((range, item) => {
            const rangedIndex = range.reduce((ranged, rangedCollection, index) =>
              rangedCollection.indexOf(item - 1) > -1 ? index : ranged,
              -1
            );
      
            if (rangedIndex > -1) {
              range[rangedIndex] = range[rangedIndex].concat(item);
      
              return range;
            }
      
            return range.concat([
              [item]
            ]);
          }, [
            [sorted[0]]
          ])
          .map(range => range.length > 1 ?
            '' + range[0] + '-' + range[range.length - 1] :
            '' + range[0]
          )
          .join(',');
      }
      
      console.log(summarizeRange([0,3,2,6,19,20,22,21,1]));

      【讨论】:

        猜你喜欢
        • 2012-01-27
        • 1970-01-01
        • 2017-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 2018-11-02
        相关资源
        最近更新 更多