如何获取JavaScript数组的所有子字符串(连续子序列)?

18
我的任务是使用JavaScript将给定的数组拆分成较小的数组。例如,[1, 2, 3, 4]应该被拆分为[1] [1, 2] [1, 2, 3] [1, 2, 3, 4] [2] [2, 3] [2, 3, 4] [3] [3, 4] [4]
我正在使用以下代码:
let arr = [1, 2, 3, 4];

for (let i = 1; i <= arr.length; i++) {
  let a = [];
  for (let j = 0; j < arr.length; j++) {
    a.push(arr[j]);
    if (a.length === i) {
      break;
    }
  }
  console.log(a);
}

我得到了以下结果:[1] [1, 2] [1, 2, 3] [1, 2, 3, 4] undefined

我错过了什么/做错了什么?


我认为你应该在循环开始处将j=i设置 - Alexandr Kudryashov
将 j 设为 i,并移除嵌套循环中的 if 条件。 - user9628338
将i初始化为0,并在相应的条件中删除=符号。 - user9628338
请您在提建议前先亲自尝试一下,确保其可行性。 - Krisztián Balla
1
@rockstar 不,这不正确。 - IntoTheDeep
显示剩余2条评论
6个回答

16

对于内部数组,您可以从外部数组的索引开始。

var array = [1, 2, 3, 4],
    i, j, l = array.length,
    result = [];
    
for (i = 0; i < l; i++) {
    for (j = i; j < l; j++) {
        result.push(array.slice(i, j + 1));
    }
}
console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }


这个程序会创建一个大数组,目标是创建小数组。 - IntoTheDeep
你对小数组有什么需求?你可以展示子数组而不是推入它们。 - Nina Scholz

11

你的代码有两个问题:

  1. 你需要循环初始化内部循环的值为i的值,以便它考虑下一个索引进行新的i迭代。
  2. 你需要在内部循环中删除break长度。

let arr = [1, 2, 3, 4];
for (let i = 0; i <= arr.length; i++) {
  let a = [];
  for (let j = i; j < arr.length; j++) {
    a.push(arr[j]);
    console.log(a);
  }
}


值得注意的是,此代码在内部循环的连续迭代中记录并修改相同数组a。诚然,这也是OP代码的做法,但对于试图天真地修改此代码(例如将所有子序列收集到单个数组中并返回)的任何人来说,这可能会令人惊讶。Nina Scholz的答案提供了一个更易于推广的解决方案,使用.slice() - Ilmari Karonen
1
外层循环应该使用 < 而不是 <=。目前它会多做一次迭代,只是为了在下一行检查 j < arr.length 后被中断。 - Salman A

2

试试这个

 let arr = [1, 2, 3, 4];
       for (let i = 0; i <= arr.length; i++) {
          let a = [];
          for (let j = i; j < arr.length; j++) {
            a.push(arr[j]);    
              console.log(a);            
          }  
        }


4
你为什么需要 tmp 变量? - Krisztián Balla
你可以不使用临时变量来完成它=) - Alexandr Kudryashov

0
我已为此情况准备好了stackblitz
let source = [1,2,3,4];
const output = [];
const arrayMultiplier = (source) => {
  const eachValueArray = [];
  source.forEach((item, index) => {
    // Will push new array who will be sliced source array.
    eachValueArray.push(source.slice(0, source.length - index));
  });
  //We reverse array to have right order.
  return eachValueArray.reverse();
};

for(let i = 0; i <= source.length; i++) {
  output.push(...arrayMultiplier(source));
  source.shift();  // Will recraft source array by removing first index.
}
//Don't forget last item.
output.push(source);
console.log(output);

虽然不是最简短的解决方案,但能够完成工作。

== 代码审核后更新 ==

// [...]
const arrayMultiplier = (source) => {
    // Will push new array who will be sliced source array.
    // We reverse array to have right order.
  return source.map((item, index) => source.slice(0, source.length - index)).reverse();
};
// [...]

避免使用 forEach + push,改用 map - Bergi

0
如果您不想改变您的数组。
    let arr = [1, 2, 3, 4];
    let res = [];
    for (let i = 0; i <= arr.length; i++) {
      let a = [];
      for (let j = i; j < arr.length; j++) {
        a = [...a, arr[j]];
        res = [...res, a];
      }
    }
 console.log(res);

0

使用两个迭代

  1. 根据循环索引获取切片数组。
  2. 使用切片数组并组合数组元素。

  var arr = [1, 2, 3, 4];
  let newArra =[];
  arr.map((x,i)=> {
       let remainArr = arr.slice(i);
       return remainArr.forEach((y, r) => newArra.push(remainArr.slice(0, r+1)))
  })
  newArra.forEach(x=> console.log(x))


1
@EricDuminil 谢谢,已经做出了必要的更改。 - Anoop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接