I have data like this :
const cards = [
{ name: "angular2" },
{ name: "vue" },
{ name: "react" },
{ name: "grunt" },
{ name: "phantomjs" }
];
I want to duplicate and shuffle this array. Also i want to add id
property to each item.
const duplicateCards = (arr) => {
const dublicatedArr = [...arr, ...arr];
for (let i = dublicatedArr.length - 1; i >= 0; i--) {
dublicatedArr[i].id = i;
console.log(dublicatedArr[i]);
[dublicatedArr[i], dublicatedArr[randomIndex]] = [dublicatedArr[randomIndex],dublicatedArr[i]];
}
return dublicatedArr;
};
duplicateCards(cards)
This function gives an output like this:
[
{ name: 'vue', id: 1 },
{ name: 'angular2', id: 0 },
{ name: 'vue', id: 1 },
{ name: 'grunt', id: 7 },
{ name: 'phantomjs', id: 4 },
{ name: 'phantomjs', id: 4 },
{ name: 'grunt', id: 7 },
{ name: 'react' },
{ name: 'react' },
{ name: 'angular2', id: 0 }
]
I tried concat()
method but i got same result.I wanted to add a unique id. What is my mistake ? How can i solve this?
CodePudding user response:
This happens because although you spread the array with [...arr, ...arr]
, creating a new array, the object references are still the same, so every object is now referenced twice. This means that any mutation you do (like with assigning to the id
property) will be visible at two places in the array.
Secondly, you should assign the id
property before the phase where you start swapping, as you may meet the same object a second time and then assign a different id
to it, while other objects, which get swapped to the index i
, will not get an id
assigned.
Here is how it could work, by chaining a .map
on the created array which creates new objects:
const duplicateCards = (arr) => {
const dublicatedArr = [...arr, ...arr].map((o, id) => ({...o, id }));
for (let i = dublicatedArr.length - 1; i >= 0; i--) {
let randomIndex = Math.floor(Math.random() * i);
[dublicatedArr[i], dublicatedArr[randomIndex]] = [dublicatedArr[randomIndex],dublicatedArr[i]];
}
return dublicatedArr;
};
const cards = [
{ name: "angular2" },
{ name: "vue" },
{ name: "react" },
{ name: "grunt" },
{ name: "phantomjs" }
];
console.log(duplicateCards(cards));
CodePudding user response:
You can use the Fisher-Yates algorithm to shuffle the elements after duplicating them using Array#flatMap
:
const _shuffleArr = arr => {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i 1));
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
}
const duplicateCards = (arr = []) =>
_shuffleArr(
arr.flatMap((card, id) => [ { ...card, id }, { ...card, id } ])
);
console.log( duplicateCards([ { name: "angular2" }, { name: "vue" }, { name: "react" }, { name: "grunt" }, { name: "phantomjs" } ]) );