Michael Durrant
Michael Durrant

Reputation: 96454

How to ensure a js array respects element order when I add them to a containing array?

I am looping thru an array and trying to find where two elements sum to 10.

I find the correct match pairs... but for two of them the order is not retained when they are added.

I expect to get

[ [9,1], [6,4], [3,7], [7,3], [6,4], [1,9] ]

but I get

[ [9,1], [6,4], [3,7], [3,7], [6,4], [9,1] ]

i.e.  =>                ^^^           ^^^
are different

Why do the two pairs indicated have their order backwards ?

  newNums = [];
  nums.forEach(num1 => {
    nums.forEach(num2 => {
      num1Position = nums.indexOf(num1);
      num2Position = nums.indexOf(num2);
      if (num1 + num2 === 10 && num2Position > num1Position )  {
        newNums.push([num1, num2]);
      }
    })
  })
  return newNums;
}

result = sumTwoNumbersIsTen([9,6,3,7,3,6,4,2,0,1,9])
console.log(result); // should be [ [9,1], [6,4], [3,7], [7,3], [6,4], [1,9] ]
// but I get                      [ [9,1], [6,4], [3,7], [3,7], [6,4], [9,1] ]
//                

Upvotes: 1

Views: 30

Answers (3)

Nina Scholz
Nina Scholz

Reputation: 386520

You could iterate with indices and omit parts who are not valid.

BTW, it is a good idea to declare all variables.

const sumTwoNumbersIsTen = nums => {
    const newNums = [];
    for (let i = 0; i < nums.length - 1; i++) {
        const num1 = nums[i];
        for (let j = i + 1; j < nums.length; j++) {
            const num2 = nums[j];
            if (num1 + num2 === 10) {
                newNums.push([num1, num2]);
            }
        }
    }
    return newNums;
};

console.log(sumTwoNumbersIsTen([9, 6, 3, 7, 3, 6, 4, 2, 0, 1, 9])); // [[9, 1], [6, 4], [3, 7], [7, 3], [6, 4], [1, 9]]

Upvotes: 3

Robin Zigmond
Robin Zigmond

Reputation: 18249

The problem is that there are (for example) two 9s in the array, and .indexOf only finds the index of the first occurence.

You can solve this by not using indexOf and instead exploiting that the callback to forEach can take a second parameter which is the element's index:

function sumTwoNumbersIsTen(nums) {
  newNums = [];
  nums.forEach((num1, num1Position) => {
    nums.forEach((num2, num2Position) => {
      if (num1 + num2 === 10 && num2Position > num1Position )  {
        newNums.push([num1, num2]);
      }
    })
  })
  return newNums;
}

result = sumTwoNumbersIsTen([9,6,3,7,3,6,4,2,0,1,9])
console.log(result);

Upvotes: 0

Bergi
Bergi

Reputation: 664196

Because you're using the wrong positions. Instead of taking the position of the element from the current iteration, which forEach passes to your callback, you are searching for an index in the array where the value could be found. For duplicate values, this will always find the first index, not the one you want (and also it's horribly inefficient).

newNums = [];
nums.forEach((num1, num1Position) => {
  nums.forEach((num2, num2Position) => {
    if (num1 + num2 === 10 && num2Position > num1Position )  {
      newNums.push([num1, num2]);
    }
  })
})

Upvotes: 1

Related Questions