0

I try to add new property "id" to an array of object. The reson I don't to this in the begining is because first I have to sort the array in a random order. I try to do this with a loop, alse with forEach, but it doesn't work. Why?

    CreateCardList = () => {
        const { cardsAmount } = this.state;
        let halfList = [];
        let card = {};
        for (let i = 0; i < cardsAmount/2; i++) { // choose cards for half of the amount
            card = {
                type: 'hero',
                isHidden: true
            }
            halfList.push(card);
        }
        let entireCardList = [...halfList, ...halfList]; // duplicate the array
        entireCardList.sort((a, b) => 0.5 - Math.random()); // sorting the array in random order
        for (let j = 0; j < entireCardList.length; j++) {
            entireCardList[j].id = j;
        }
        console.log(entireCardList);
    }

In the console I got the below array. If I refrush, the id numbers change but still it is not ordered.

0: {type: "hero", isHidden: true, id: 9}
1: {type: "hero", isHidden: true, id: 7}
2: {type: "hero", isHidden: true, id: 10}
3: {type: "hero", isHidden: true, id: 5}
4: {type: "hero", isHidden: true, id: 11}
5: {type: "hero", isHidden: true, id: 5}
6: {type: "hero", isHidden: true, id: 8}
7: {type: "hero", isHidden: true, id: 7}
8: {type: "hero", isHidden: true, id: 8}
9: {type: "hero", isHidden: true, id: 9}
10: {type: "hero", isHidden: true, id: 10}
11: {type: "hero", isHidden: true, id: 11}

3 Answers 3

1

Your problem comes from this line: let entireCardList = [...halfList, ...halfList];
You are trying to create a completly new array by thinking that you are duplicating the halfList, but what is instead happening; the spread operator will not create a deep copy of array so it is just shallow copied. And when you assign a id to one item from the list, it is actually assigned to multiple, since they have the same reference.

one solution replace this: let entireCardList = [...halfList, ...halfList]; with:

const firstHalf = JSON.parse(JSON.stringify(halfList));
const secondHalf = JSON.parse(JSON.stringify(halfList));
let entireCardList = [...firstHalf, ...secondHalf];

And it should work as expected :)

Working example:

const cardsAmount = 6
const halfList = [];

for (let i = 0; i < cardsAmount / 2; i++) {
  halfList.push({ type: 'hero', isHidden: true });
}

const firstHalf = JSON.parse(JSON.stringify(halfList));
const secondHalf = JSON.parse(JSON.stringify(halfList));
const entireCardList = [...firstHalf, ...secondHalf];

// If cards are the same, then there is no point in sorting...
entireCardList.sort((a, b) => 0.5 - Math.random());

for (let j = 0; j < entireCardList.length; j++) {
  entireCardList[j].id = j;
}

console.log(entireCardList);

Sign up to request clarification or add additional context in comments.

4 Comments

I think there is no need to deep clone firstHalf
It works! But still I don't understand what JSON.stringify and JSON.parse do? Can I use something more simple to duplicating like concat function? Example: halfList.concat(halfList)
@liorbar JSON stringify/parse is a way in javascript just to clone things deeply (it means really to provide a new reference in memory) check this out: stackoverflow.com/questions/122102/…
@V.Sambor Thanks so much!! You help me a lot with my project.
1

When you make card entireCardList you do not duplicate objects, so you end up with [object1, object2, ... , object1, object2, ...] array. So when you assign id it just overrides values. To fix this you can create copies of objects for second half of the array:

let entireCardList = [...halfList, ...halfList.map(x => ({...x}))]

PS Does not make any sense for me to sort array in random order which contains exactly same elements

8 Comments

I do it for create memory cards game. I still don't understand this point. What I should do to fix this?
You should create copies of objects for second half of the array. For example like this: let entireCardList = [...halfList, ...halfList.map(x => ({...x}))];
This solution is problematic. If someone modifies an item in halfList the entireCardList first part will be modified as well... so I would not relay on this.
@V.Sambor Who will modify an item in halfList? It is not being returned anywhere and just used as temporary var to create entireCardList
How do you know is temporary ? since it is declared in the global scope...
|
0

Because you create an array that contains pairs of refs to objects, thats why :)

let entireCardList = [...halfList, ...halfList];

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.