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));