0

I have a Matrix contained in a 2D-array:

var testM = [
[0.0,2.0,3.0],
[1.0,1.0,1.0],
[7.0,5.0,6.0]
];

// swap row a with b
function swapRows(a,b){
  let temp = a.slice(); // Copy by value, not reference
  a = b.slice();
  b = temp;
}

// The individual arrays are passed in:
swapRows(testM[0], testM[1]);

However, the original 2D array remains unchanged after running the above code. I'm not too familiar with passing by reference in javascript, so any help is appreciated. (Note: it works fine when pasted inline, just wondering why it doesn't function even when copied by value)

EDIT: I completely understand how to swap the elements of a regular, one-dimensional array; I was inquiring more about about the mechanics of passing by reference in javascript. (I don't even know if I'm using the right terminology)

Tony
  • 230
  • 4
  • 11
  • 1
    Pass the array itself to the function: https://jsfiddle.net/y2vk9m6e/1/ – Gerardo Furtado Oct 06 '18 at 13:33
  • 1
    possible duplicate https://stackoverflow.com/questions/4011629/swapping-two-items-in-a-javascript-array – PrathapG Oct 06 '18 at 13:34
  • Possible duplicate of [Swapping two items in a javascript array](https://stackoverflow.com/questions/4011629/swapping-two-items-in-a-javascript-array) – choz Oct 06 '18 at 13:39
  • @PrathapG Those are not talking about swapping the elements of a 2D array - if this was a regular int array, the elements would swap fine. – Tony Oct 06 '18 at 13:46
  • If you want to manipulate an array, maybe you should add some method to your array. In doing so, you'll be able to swap rows: testM.swap(0,1) – parameciostudio Oct 06 '18 at 13:57
  • 1
    See this [`post`](https://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value) :) – C.RaysOfTheSun Oct 06 '18 at 14:11

2 Answers2

2

Your code doesn't work because assigning to a and b inside your function doesn't change the references in the original table.

You pass the function a reference to two of the internal arrays from the table. The function creates local variables a and b each pointing to one of those references. When you swap a and b all you have done is changed which array reference the local variables point to. You haven't changed anything in the original table. To do that you need a reference to the table itself so you can swap what its array references point to. Something like:

var testM = [
    [0, 2, 3],
    [1, 1, 1],
    [7, 5, 6]
    ];
    
// swap row a with b
function swapRows(table, a, b){
    [table[a], table[b]] = [table[b], table[a]]
}

// Table and indexes passed in:
swapRows(testM, 0, 1);
console.log(testM)

If you were dead set on passing in the individual arrays, you could replace all the values of one array with the other. This is really inefficient though:

var testM = [
    [0, 2, 3],
    [1, 1, 1],
    [7, 5, 6]
    ];
    
// swap row a with b
function swapRows(a,b){
    let temp = a.slice(); // Copy by value, not reference
    a.splice(0, a.length, ...b);
    b.splice(0, b.length, ...temp);
}

// The individual arrays are passed in:
swapRows(testM[0], testM[1]);
console.log(testM)
Mark
  • 90,562
  • 7
  • 108
  • 148
1

Edit

You can't alterate a primitive (string, number, bigint, boolean, null, undefined, and symbol) because primitives are immutable.(https://developer.mozilla.org/en-US/docs/Glossary/Primitive)

If you pass the array as an argument, you can alterate it inside your function.


swapRows(testM, 0, 1);

function swapRows(arr,a,b){   // <-- arr = testM. The value is an ARRAY, therefore it can be alterate (it's not a primitive) 
  let temp = arr[a].slice(); 
  arr[a] = arr[b].slice();
  arr[b] = temp;
}

Old

Basically, you can't pass a variable as a reference in javascript. (This sentence isn't correct. See "Edit")

If you want to manipulate an object, you can adopt one of these methods:

  1. Assign a new value using a function that returns the computed value
  2. Modify the object (some property of the object) by using a method

Function

You have to pass the object (array) as an argument of the function

function swapRows(arr,a,b){
  let temp = arr[a].slice(); // Copy by value, not reference
  arr[a] = arr[b].slice();
  arr[b] = temp;
  return arr;
}

testM = swapRows(testM, 0, 1);

Method

You can extend the object or the prototype (some caveat here: JavaScript: What dangers are in extending Array.prototype?)

Array.prototype.swapRows = function(a,b){
  let temp = this[a].slice(); // Copy by value, not reference
  this[a] = this[b].slice();
  this[b] = temp;
  return this;
}

testM.swapRows(0, 1);
parameciostudio
  • 570
  • 5
  • 12