0

I'm new to JS and am trying to create a simple 'swap array elements if array A element is bigger than array B element' function. In the swapIndexes function, I don't understand why I can't define the variables as shown in the comments. For example, it works if it state arrA[c] rather than let a = arrA[c].

Why does this happen? Can anyone give some beginner tips on how best to go about something like this? My code feels verbose. Thanks for any help here.

var arrA = [0, 1, 2, 7, 6],
  arrB = [0, 1, 2, 5, 7],
  indexesToSwap = [],
  aValuesToSwap = [],
  bValuesToSwap = [],
  needSwapping = false;

arrA.forEach(getSwappableIndexesAndValues);
indexesToSwap.forEach(swapIndexes);

function getSwappableIndexesAndValues(c, i) {
  let b = arrB[i];

  if (c > b) {
    needSwapping = true;
    indexesToSwap.push(i);
    aValuesToSwap.push(b);
    bValuesToSwap.push(c);
  }
}

function swapIndexes(c, i) {
  //let a = arrA[c];  fails why???
  //let b = arrB[c];  fails why???
  //a = aValuesToSwap[i];  fails why???
  //b = bValuesToSwap[i];  fails why???

  arrA[c] = aValuesToSwap[i];
  arrB[c] = bValuesToSwap[i];
}

console.log(arrA);
console.log(arrB);
user8758206
  • 2,106
  • 4
  • 22
  • 45
  • your `indexesToSwap` is empty as I see – Artyom Amiryan Nov 01 '18 at 12:07
  • no, it contains: [3] – user8758206 Nov 01 '18 at 12:11
  • My first question would be, from where do the `(c, i)` parameters come from, in **both** the functions..? I don't see any `c` variable / value (or any other parameter) outside those functions that will be passed into the functions themselves..? – Petar Nov 01 '18 at 12:13
  • Basically when you do `let a = arrA[c]` you are getting the value at the index `c` from your array and setting it equal to `a`. So you are not setting `a` equal to the literal instance `arrA[c]`, but rather the value at index `c` in your array (which is just a number in your case). – Nick Parsons Nov 01 '18 at 12:16
  • @Petar - the c is the current value and i is the index value of the arrays that run the function (e.g. arrA goes through a forEach). – user8758206 Nov 01 '18 at 12:20
  • 1
    `arrA[c] = aValuesToSwap[i]; arrB[c] = bValuesToSwap[i];` This operation is meaning less reassigning same values. This may be your logical error. – Sumesh TG Nov 01 '18 at 12:20
  • @NickParsons I don't understand why, because that would presumably be the case is it was let a = c, and the array shows no change anyway? – user8758206 Nov 01 '18 at 12:22
  • 1
    When you do `let a = arrA[c]` you have to ask yourself "is arrA[c] a simple type?" (a number, string or boolean). If so you get a copy of that value in a, otherwise you get a reference to whatever the object at arrA[c] is. Since your values are all simple values, you don't get references to work with. – James Nov 01 '18 at 12:29
  • 1
    If you `let a = c` then you're just assigning the variable `a` to be equal to a number and thus you are not modifying the array itself. Same goes for your commented out code `let a = arrA[c];` etc..., you are just setting `a` to be a number ("copied" out of the array, but when modified not modified in the array itself), so when you overwrite `a` later on your just overwriting a number which has no connection to the original array. – Nick Parsons Nov 01 '18 at 12:31

3 Answers3

2

In javascript, when you create a variable from a given index in an array, This will create a new memory space containing a copy of the value at this index. The newly created variable will not point to the content of the array and thus, modifying this variable will not modify the content of the array.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

Tezirg
  • 1,629
  • 1
  • 10
  • 20
1

var arrA = [0, 1, 2, 7, 6],
  arrB = [0, 1, 2, 5, 7],
  indexesToSwap = [],
  aValuesToSwap = [],
  bValuesToSwap = [],
  needSwapping = false;

arrA.forEach(getSwappableIndexesAndValues);
indexesToSwap.forEach(swapIndexes);

function getSwappableIndexesAndValues(c, i) {
  let b = arrB[i];

  if (c > b) {
    needSwapping = true;
    indexesToSwap.push(i);
    aValuesToSwap.push(b);
    bValuesToSwap.push(c);
  }
}

function swapIndexes(c, i) {
  //let a = arrA[c];  fails why???
  //let b = arrB[c];  fails why???
  //a = aValuesToSwap[i];  fails why???
  //b = bValuesToSwap[i];  fails why???

  arrA[c] =   bValuesToSwap[i];
  arrB[c] =aValuesToSwap[i];
  console.log(  arrA[c], arrB[c]);
  console.log(   aValuesToSwap[i],  bValuesToSwap[i]);
}

console.log(arrA);
console.log(arrB);
It is not possible array values and primitive data type values are different. If you try with the array of the object your attempt will be correct.
Sumesh TG
  • 2,557
  • 2
  • 15
  • 29
  • sorry, I don't think I was clear. The output it already correct (i.e. [0, 1, 2, 5, 6] and [0, 1, 2, 7, 7]) but the problem is I don't understand why replacing the 2 lines 'arrA[c] = aValuesToSwap[i];' and 'arrB[c] = bValuesToSwap[i];' with the 4 lines commented out doesnt work – user8758206 Nov 01 '18 at 12:25
  • Ok.. Let me check – Sumesh TG Nov 01 '18 at 12:26
  • 1
    It is not possible array values and primitive data type values are different. If you try with the array of the object your attempt will be correct. Refer https://stackoverflow.com/questions/6612385/why-does-changing-an-array-in-javascript-affect-copies-of-the-array – Sumesh TG Nov 01 '18 at 12:31
1

indexesToSwap has all the information you need to swap. The swap value arrays (aValuesToSwap, bValuesToSwap) are greatly complicating matters and are wholly unnecessary.

Regardless of the values to swap arrays, swapping is a fundamental operation and typically involves a simple temporary, e.g.

temp = arrA[i];
arrA[i] = arrB[i];
arrB[i] = temp;

Discarding the complexities, here's an alternative to the function getSwappableIndexesAndValues

function getSwappableIndexes(c, i) {     
  if (c > arrB[i])
    indexesToSwap.push(i);           
}

And a simplified swap function

function swapIndexes(c, i) {
  let temp = arrA[c];
  arrA[c] = arrB[c];
  arrB[c] = temp;    
}

I have to say further though that the use of Array.forEach wildly complicates the entire solution. Unless this is an assignment, using a simple for-loop is best here.

// swaps values between arrays where the value in 
// array a is greater than the value in array b
//
function swapIfGreaterThan(a,b) {
   for(let i = 0; i < a.length && i < b.length; i++) {
      if(a[i] > b[i]) {
         let temp = a[i];
         a[i] = b[i];
         b[i] = temp;
      }
   }
}
RamblinRose
  • 4,883
  • 2
  • 21
  • 33