Given an array arr and an array of indices ind, I\'d like to rearrange arr in-place to satisfy the given indices. For exa
This answer has been updated to satisfy OP's conditions
In this answer there are no temp arrays and ind array doesn't get re-ordered or sorted by any means. All replacing operations are done in a single pass. getItemIndex function receives only a shallow portion of the ind array to work with. It's just done by harnessing all the information hidden in the ind array.
It's key to understand that the ind array keeps all history for us.
We have the following information by examining the ind array.
arr array.ind.indexOf(i); Anyways here is the code;I have added a few functions like Array.prototype.swap() to make the code interpreted easier. Here is the code.
Array.prototype.swap = function(i,j){
[this[i],this[j]] = [this[j],this[i]];
return this;
};
function getItemIndex(a,i){
var f = a.indexOf(i);
return f !=-1 ? getItemIndex(a,f) : i;
}
function sort(arr,ind){
ind.forEach((n,i,x) => x.indexOf(i) > i ? arr.swap(i,x[i]) // item has not changed before so we can swap
: arr.swap(getItemIndex(ind.slice(0,i),i),x[i])); // item has gone to somwhere in previous swaps get it's index and swap
return arr;
}
var arr = ["A", "B", "C", "D", "E", "F"],
ind = [4, 0, 5, 2, 1, 3];
console.log(sort(arr,ind),ind);
Ok the very final version of this code is this. It is very simplified and includes a test case with 26 letters. Each time you run you will get a different purely random unique indexes map.
Array.prototype.swap = function(i,j){
i !=j && ([this[i],this[j]] = [this[j],this[i]]);
return this;
};
Array.prototype.shuffle = function(){
var i = this.length,
j;
while (i > 1) {
j = ~~(Math.random()*i--);
[this[i],this[j]] = [this[j],this[i]];
}
return this;
};
var arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
ind = (new Array(arr.length)).fill("").map((e,i) => e = i).shuffle();
console.log(JSON.stringify(arr));
console.log(JSON.stringify(ind));
function getItemIndex(a,i,j){
var f = a.indexOf(i);
return f < j ? getItemIndex(a,f,j) : i;
}
function sort(arr,ind){
ind.forEach((n,i,x) => arr.swap(getItemIndex(ind,i,i),n));
return arr;
}
console.log(JSON.stringify(sort(arr,ind)));
console.log(JSON.stringify(ind));
So ok as per the comment from Trincot here it goes with an iterative getItemIndex() function.
Array.prototype.swap = function(i,j){
i !=j && ([this[i],this[j]] = [this[j],this[i]]);
return this;
};
Array.prototype.shuffle = function(){
var i = this.length,
j;
while (i > 1) {
j = ~~(Math.random()*i--);
[this[i],this[j]] = [this[j],this[i]];
}
return this;
};
var arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
ind = (new Array(arr.length)).fill("").map((e,i) => e = i).shuffle();
console.log(JSON.stringify(arr));
console.log(JSON.stringify(ind));
function getItemIndex(a,i){
var f = a.indexOf(i),
j;
if (f >= i) return i; // this element hasn't been moved before.
while (f < i) { // this element has been swapped so get this elements current index
j = f;
f = a.indexOf(f);
}
return j;
}
function sort(arr,ind){
ind.forEach((n,i,x) => arr.swap(getItemIndex(ind,i),n));
return arr;
}
console.log(JSON.stringify(sort(arr,ind)));
console.log(JSON.stringify(ind));