Algorithm mixing information of two arrays of objects in javascript?

Viewed 49

Problem

I have this array

const cards = [
    {id: "29210z-192011-222", power: 0.9}, // Card A
    {id: "39222x-232189-12a", power: 0.2} // Card B
    ...
]

My firestore database looks like this:

cards (collection) -> cardId (document) -> userId (a "Foreign Key" to the card's owner, in the document data)

So, I get the corresponding owner for each card I have in my array:

const documentRefs = cards.map((card) =>
    firestore.collection("cards").doc(card.id)
);

const rivalPlayers = db.collection("cards")
                  .getAll(...documentRefs)
                  .then((docs) => {
                      return docs.map(doc => {
                         console.log(doc.data); // { userId: "219038210890-234-22-a" }  
                         /*
                            TODO - Here I need to return an object containing the userId (from doc.data)
                            and the power of the card which referenced him
                         */
                       })
                   })
                   .catch(err => throw err);

As you can see in the code, I need as result an array "rivalPlayers" looking like this:

[{userId: "219038210890-234-22-a", power: 0.9}, {userId: "519aa821Z890-219-21-e", power: 0.2}]

Pd: This array can't contain the current user, so I filter it

Question

Does anybody know how to mix the arrays information in this situation? I mean, in the moment I map the documents from firebase I have the userId (which correspond to a card from the cards array) and the cardId (doc.id, as each document id in my database is a card id), but I don't know how to get each power with a good performance.

I would appreciate that the solution is written in modern javascript. Thanks.

My best approach

const rivalPlayers = db.collection("cards")
                  .getAll(...documentRefs)
                  .then((docs) => {
                       return docs.map(doc => ({
                          userId: doc.data.userId,
                          power: cards.filter(card => card.id === doc.id)[0].power // <----------- That is the main point of the question
                       })).filter(player => player.userId !== currentUser.userId) // This part is irrelevant to my question
                   })
                   .catch(err => throw err);

Try this code fast

I know that this scenario is a little long to build, as you have to recreate the firebase database, etc...

Here is the same code without fetching data from firebase:

const cards = [
    {id: "29210z-192011-222", power: 0.9}, // Card A
    {id: "39222x-232189-12a", power: 0.2} // Card B
]

const usersIds = [
  {
    id: "39222x-232189-12a", // Firebase doc.id === card id
    data: {
      userId: "329u4932840" // Id of the owner of the card
    }
  },
  {
    id: "29210z-192011-222", // Firebase doc.id === card.id
    data: {
      userId: "8u4394343" // Id of the owner of the card
    }
  }
]

const rivalPlayers = usersIds.map(doc => ({
                          userId: doc.data.userId,
                          power: cards.filter(card => card.id === doc.id)[0].power
                      }));

console.log(rivalPlayers)

Try it on https://playcode.io/ for example.

1 Answers

Put all the power values in a Map so you only need to iterate through cards once instead of running a filter() many times

const cards = [{id: "29210z-192011-222", power: 0.9}, {id: "39222x-232189-12a", power: 0.2}];

const powerMap = new Map(cards.map(({id, power}) => [id, power]));
const wantedId = "39222x-232189-12a"

console.log('Power for id:', wantedId , 'is:', powerMap.get(wantedId))

Related