代码之家  ›  专栏  ›  技术社区  ›  Kamil Kiełczewski

从已排序的整数数组创建字符串范围

  •  11
  • Kamil Kiełczewski  · 技术社区  · 6 年前

    我有以下排序的数字数组(它们可以重复,例如21)

    let a = [1,2,3,4,7,8,12,15,21,21,22,23]
    

    并希望获得具有范围的字符串数组(已排序)

    let r =["1-4","7-8","12","15","21-23"]
    

    对于连续的数字a,a+1,a+2,…,a+n=b w必须创建字符串“a-b”,例如,对于6,7,8,我们希望得到“6-8”,对于“单独”的数字,我们希望只得到该数字,例如,对于上述示例中的12,我们得到“12”。

    这是我的尝试,但我坚持下去了(而且头疼)

    let a = [1,2,3,6,7,8,12,15,21,21,22,23];
    let right=a[0];
    let left=a[0];
    let result=[];
    
    for(let i=1; i<a.length; i++) {
    	for(let j=1; j<a.length; j++) {
          if(a[i]<a[j])result.push(`${a[i]}-${a[j]}`);
          
      }
    }
    
    console.log(JSON.stringify(result));
    5 回复  |  直到 6 年前
        1
  •  7
  •   Nina Scholz    6 年前

    您可以将下一个期望值存储在一个闭包中并减少数组。

    function getRanges(array) {
        return array.reduce((l => (r, v, i, a) => {
            if (l[1] > v) return r;
            r.push(l[1] === v
                ? (r.pop(), l.join('-'))
                : (l = [v, v]).slice(0, 1).toString()
            );
            l[1]++;
            return r;
        })([]), []);
    }
    
    console.log(getRanges([-3, -2, -1, 2]));
    console.log(getRanges([1, 2, 3, 4, 7, 8, 12, 15, 21, 21, 22, 23]));
        2
  •  3
  •   jmcgriz    6 年前

    这应该对你有用。

    const a = [1,2,3,4,7,8,12,15,21,21,22,23,27]
    
    let min = a[0], last = a[0]
    
    const result = a.reduce((arr, n, i) => {
      if(n - last > 1){
        if(min == last) arr.push(""+min)
        else arr.push([min, last].join("-"))
        
        min = n
      }
      
      if(i == a.length - 1) {
        if(min == n) arr.push(""+min)
        else arr.push([min, n].join("-"))
      }
      
      last = n
      
      return arr
    }, [])
    
    console.log(result)
        3
  •  2
  •   Kamil Kiełczewski    6 年前

    另一种方法可能是

    let a = [1,2,3,4,7,8,12,15,21,21,22,23]
    
    let r = a.reduce((acc, val) => {
      const lastGroup = acc.pop() || [];
      const lastValue = lastGroup.slice(-1)[0];
      if (val - lastValue > 1) {
        return [...acc, lastGroup, [val]];    
      }
      return [...acc, [...lastGroup, val]];
    }, []).map(group => {
      const first = group[0];
      const last = group[group.length-1];
      return first !== last ? `${first}-${last}` : `${first}`;
    });
    
    console.log(r)
        4
  •  2
  •   Jonas Wilms    6 年前

    你不需要两个循环,只要跟踪你是不是启动了团队:

    let array = [1,2,3,4,7,8,12,15,21,21,22,23]
    
    const groups = [];
    let start = array[0];
    
    array.push(NaN);
    
    for(let index = 1; index < array.length; index++) {
      const value = array[index], previous = array[index - 1];
      if(value === previous + 1 || value === previous) 
         continue;
    
      if(start === previous) {
        groups.push("" + previous);
      } else {
        groups.push(start + "-" + previous);
      }
      start = value;
    }
    
    console.log(groups);
        5
  •  0
  •   Kamil Kiełczewski    6 年前

    这也是我的答案(受到其他答案的启发)

    let r = (a,c='-',f=a[0],g=[]) => (a.map((x,i,a,b=a[i+1]) =>
            b<=x+1 ? 0 : (g.push( f-x ? f+c+x : f+'' ),f=b) ),g);
    

    let a = [1,2,3,4,7,8,12,15,21,21,22,23];
    let b = [-7,-5,-4,-3,-1,0,1,3,4,5,8]; 
    
    let r = (a,c='-',f=a[0],g=[]) => (a.map((x,i,a,b=a[i+1]) =>
            b<=x+1 ? 0 : (g.push( f-x ? f+c+x : f+'' ),f=b) ),g);
    
    let J= JSON.stringify;
    console.log(J(a) + ' -> ' + J(r(a)));
    console.log(J(b) + ' -> ' + J(r(b,'..')));

    说明:G=[]包含结果,第一个范围元素是 f=a[0] ,开始时,我们检查是否执行下一个元素 b=a[i+1] 等于或小于当前元素x加1 b<=x+1 . 如果没有(这意味着范围结束或 i 最后一个索引是-b=未定义),然后我们将范围推到结果 g.push( f-x ? f+'-'+x : f+'' ) (我们在这里检查x不等于f f-x -> f-x!=0 -> f!=x )推设第一量程元件后 f 到下一个范围(元素 b )