1

I'm trying to animate the sorting of a few elements with jQuery and my sorting map is defined like this:

var mapping = [
  [0, 5],
  [1, 4],
  [2, 3],
  [3, 2],
  [4, 1],
  [5, 0]
];

mapping[0][0] is the element's index and mapping[0][1] is the target index.

My solution was basically this:

var elements = [1, 2, 3, 4, 5, 6];

for (var i = 0; i < elements.length; i++) {
  var clone1 = elements[mapping[i][0]];
  var clone2 = elements[mapping[i][1]];

  elements[mapping[i][0]] = clone2;
  elements[mapping[i][1]] = clone1;
}

console.log(elements);

The problem is, I am working on the object I'm modifying and the operations undo themselves; instead of reversing the array, I get the same array back.

How would I swap elements like this in JavaScript? Here's a JSFiddle example of the code.

6 Answers 6

2
// [source, target]
var mapping = [
  [0, 5],
  [1, 4],
  [2, 3],
  [3, 2],
  [4, 1],
  [5, 0]
];

var elements = [1, 2, 3, 4, 5, 6];

function swapElements(elements, mapping) {
    var tmp = new Array(elements.length);
    for(var i = 0, l = mapping.length; i < l; i++) {
        tmp[mapping[i][1]] = elements[mapping[i][0]];
    }
    for(var i = 0, l = elements.length; i < l; i++) {
        elements[i] = tmp[i];
    }
}

swapElements(elements, mapping);

console.log(elements);​
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that was really close to what I was looking for. In my actual code, elements can have an arbitrary length and mapping is usually 2 to 5 in length, so I modified your code a little: jsfiddle.net/fxnTG/2
Ah, well, I only had the one test case.
1

Some functional fun with accessor function

var at = function(arr) { return function(i) { return arr[i] } };
[5,4,3,2,0,1].map( at(['a','b','c','d','e','f']) )

this will returns ['f','e','d','c','a','b']

Comments

0

You swap elements twice from 0 to 5 and from 5 to 0 again :) Try

for (var i = 0; i < elements.length / 2; i++)

and it will be ok.

Look here

1 Comment

Well, it's not that easy. The example mapping maps up to 5, but I have a list with 40 elements and the mapping element only contains the row swaps that occur. I used the reversing example just to illustrate my problem.
0

You're changing the array during a loop of it. And it's swapped twice for each pair, so the result is the same. You may need another arr to store mapped value:

var result = [];
for(var i = 0; i<mapping.length; i++){
    result[mapping[i][0]] = elements[mapping[i][1]];
}
console.log(result);

Comments

0

Just define a temporary array:

var elements = [1, 2, 3, 4, 5, 6];
var temp = [];
for (var i = 0; i < elements.length; i++) {
  temp.push(elements[mapping[i][1]]);
}
elements = temp;

Comments

0

Just_Mad's answer is correct if you are only trying to reverse the list. But if you want to be able to handle any mapping configuration you will need a different approach.

If you don't care about memory space you could just iterate through the mapping list and copy the element at index "mapping[i][0]" to a new array at index "mapping [i][1]". Then just return the new array. This should handle whatever mapping you put into the system (you just have to decide if and how you want to handle mappings that leave empty spaces and/or override spaces)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.