将数组添加到一个数组中

6

我相信这很简单,我不需要完整的解决方案,只需要指出正确的方向,因为我正在学习。

我有:

let randomArray = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];

目标是将它分组成相似的项目,使其看起来像这样:

[[1,1,1,1],[2,2,2],[10],[20,20],[391],[392],[591]]

我的以下代码很好地进行了排序和分组。我将temp推入我的Group数组。但当我重置我的“tempArray”以使其为空准备下一个“group”时,它也会从我的group中删除数据。因为它是链接的?我猜测?或许?

最后只剩下最后一项。

我该怎么阻止它这样做?

    // My SOlution
let randomArray = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];
let tempArray = [];
let groupArray = [];

function cleanTheRoom (arr) {
    let ascendingArray = arr.sort(function(a,b) {
        return a - b;
    });
    tempArray.push(randomArray[0])
    for (let i = 1; i <= randomArray.length; i++) {
        if (randomArray[i] === tempArray[0]) {
            tempArray.push(randomArray[i])
        } else {
            groupArray.push(tempArray);
            tempArray = []
            tempArray.push(randomArray[i])
        }
    } console.log(groupArray)
}

cleanTheRoom(randomArray);

2
问题就在这里:tempArray.length = 0 应该改为 tempArray = []。 就是这么简单。 你应该将一个新数组赋值给 tempArray,否则所有的 tempArray 引用都需要保留对原始值的引用,这就是为什么会出现奇怪的日志。 当然也有更快(更简单)的方法来做到这一点。 - briosheje
如此接近,却又如此遥远。非常感谢,我所做的只是将其更改为:tempArray = []它起作用了!真的非常感激。 - Voodoo Science
我看到了一个更快的解决方案,但我想自己解决这个问题,以便从中学到更多。但是我在这里卡住了。这更像是一个练习题。 - Voodoo Science
1
要完全正确,我认为你也可以这样做:groupArray.push([...tempArray])。只要你的数组只包含基元,那么这也能完成任务。这是因为它将数组基元值推送到groupArray中,这些值不再与tempArray链接。无论哪种方式,都应该按预期工作。 - briosheje
1
还要确保在循环的最后一次迭代中将temp数组推入groupArray数组中,否则groupArray将不包含最后一个数字,即591 - Yousaf
groupArray.push([...tempArray]) 看起来并没有按照预期工作,它只是将它们列出来。不过我可能做错了什么。 我注意到最后一个项目没有被推入,我会立即处理,谢谢。 - Voodoo Science
3个回答

3

我采用了你的代码并更改了部分内容。

  • Array#sort 会原地排序,无需将其赋值给一个新变量。

  • 从0开始迭代,直接查看数据,使用索引减1处和索引处的值。如果不相等,则表示找到一个新组,此时只需将一个空数组赋值给groupArray并将组推入结果中。

    这种方法与使用相同的对象引用并通过将长度赋为零来清空数组不同,它采用了一个新数组。

  • 将值推出if语句之外,因为它在thenelse部分都被加倍了。

  • 最后返回带有组的数组。

function cleanTheRoom(array) {
    let result = [];
    let groupArray;

    array.sort(function(a, b) {
        return a - b;
    });

    for (let i = 0; i < array.length; i++) {
        if (array[i - 1] !== array[i]) {
            groupArray = [];
            result.push(groupArray);
        }
        groupArray.push(array[i]);
    }

    return result;
}

let randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

console.log(cleanTheRoom(randomArray));


谢谢,相比我的代码,你的真的很干净,而且你解释了一些对我以后有帮助的东西。 所以,array[i-1]必须从一开始就为false,因此立即创建一个数组? 我不得不通过调试器运行它才能理解它,因为它与我的大脑工作方式相反(如果相等,则跳过if语句并将其添加到groupArray中,否则创建一个新数组)。 - Voodoo Science
1
有时候,一个颠倒的视角比显而易见的更为简洁。 - Nina Scholz

1

可能有更快的方法,但我尝试了一个快速的方法:

  • 首先,我们将数组分成组
  • 然后,我们仅对组的键进行排序,而不是整个数组,以避免第二次完整迭代数组。

我使用了Map而不是字典来存储组,因为我们可以巧妙地利用Map.set函数。它返回了我们在reduce中需要作为返回值的整个Map。

const randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const isGroup = (acc, number) => Array.isArray(acc.get(number));
const setGroup = (acc, number) => acc.set(number, isGroup(acc, number) ? acc.get(number).concat([number]) : [number]);
const unorderedNumberGroups = randomArray.reduce(setGroup, new Map());
const order = [...unorderedNumberGroups.keys()].sort((a, b) => a - b);
const orderedNumberGroups = order.reduce((acc, key) => acc.concat([unorderedNumberGroups.get(key)]), []);
console.log(orderedNumberGroups);

这是一个更易于调试的版本,您可以尝试理解上面的版本:

const randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const isGroup = (acc, number) => Array.isArray(acc.get(number));
const unorderedNumberGroups = randomArray.reduce((acc, number) => {
  if (isGroup(acc, number)) {
    const mapEntry = acc.get(number);
    const newEntry = mapEntry.concat([number]);
    return acc.set(number, newEntry); // we need to return the acc, the Map.set method returns the whole Map
  } else {
    return acc.set(number, [number]); // we need to return the acc, the Map.set method returns the whole Map
  }
}, new Map()); // initialize the accumulator we an empty Map
const keysAsArray = [...unorderedNumberGroups.keys()];
const order = keysAsArray.sort((a, b) => a - b);
const orderedNumberGroups = order.reduce((acc, key) => {
  const arrayForTheKey = unorderedNumberGroups.get(key);
  return acc.concat([arrayForTheKey]); // note the breakets!

  // equivalent code:
  // acc.push(arrayForTheKey);
  // return acc;
}, []); // initialize the accumulator with an empty Array
console.log(orderedNumberGroups);


谢谢您提供的解决方案。它确实有效,并且看起来更快。但是,即使使用调试器,我也难以理解其工作原理(新手)。我将花些时间分解它,并查看是否能够理解,因为这看起来都是新的和有用的。 - Voodoo Science
1
我假设 reduce 函数和使用 ? 的快捷方式是问题的原因,对吗? - Robin F.
1
@VoodooScience 我已经添加了一个调试版本,希望更易于理解。 - Robin F.
是的,我认为他们把它做得非常困难。非常感谢,这真的很有帮助! - Voodoo Science

1

你的代码中存在三个主要问题:

  1. You are using randomArray inside the function but you should be using ascendingArray

  2. tempArray.length = 0 - this statement mutates the original tempArray and since you are pushing the tempArray array in the groupArray, changes to tempArray are reflected in the groupArray as well.

    You could clone the tempArray and push the copy of the tempArray in the groupArray

    groupArray.push([...tempArray]);
    

    or you could assign the new empty array to tempArray

    tempArray = [];
    
  3. When its the last iteration of the loop, you are not pushing the contents of the tempArray in the groupArray. This will lead to the groupArray not containing the last number in the sorted array, i.e. 591. You need to check if the current iteration is the last iteration of the loop or not. If it is, push the tempArray in the groupArray

    for (let i = 1; i < ascendingArray.length; i++) {
      ...
    
      if (i == ascendingArray.length - 1) {
        groupArray.push(tempArray);
      } 
    } 
    

Here's a simplified version of your code:

let randomArray = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

function cleanTheRoom(arr) {
  let tempArray = [];
  let groupArray = [];

  let ascendingArray = arr.sort(function (a, b) {
    return a - b;
  });

  for (let i = 0; i < ascendingArray.length; i++) {
    tempArray.push(ascendingArray[i]);

    if (ascendingArray[i + 1] !== ascendingArray[i]) {
      groupArray.push(tempArray);
      tempArray = [];
    }
  }

  console.log(groupArray);
}

cleanTheRoom(randomArray);


1
你能否编辑你的问题并展示更新后的代码,其中使用了 groupArray.push([...tempArray]);?这样只需要对你的代码进行一处更改就可以使其正常工作。 - Yousaf
1
我已经看到了更新的代码,问题在于您没有重置tempArray的长度或将其设置为空数组。 - Yousaf
我还注释掉了tempArray = [],因为我认为它是要替换这个的?否则,仅使用tempArray = []而不进行[...tempArray]更改也可以从tempArray中工作。 - Voodoo Science
1
[...tempArray] creates a copy of the tempArray so even if you do tempArray.length = 0, it won't affect the array pushed in the groupArray because groupArray will contain the copy of the tempArray - Yousaf
1
是的,tempArray.length = 0 不会影响复制的数组。 - Yousaf
显示剩余3条评论

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