How to join repeated values of an object array, only in an object of the same array?

Asked

Viewed 435 times

4

I have the following exit:

[ { rank: 1, item: { userName: 'Rafaela', score: 600 } },
  { rank: 2, item: { userName: 'Carla', score: 410 } },
  { rank: 2, item: { userName: 'Yuri', score: 410 } },
  { rank: 3, item: { userName: 'Jompas', score: 300 } },
  { rank: 4, item: { userName: 'Jonas', score: 266 } },
  { rank: 4, item: { userName: 'Tereza', score: 266 } },]

Rank draws are displayed one below the other with the same placement. I would like to know a way to take these draws and save within one object, to receive the following output:

[ 
    { rank: 1, item: { userName: ['Rafaela'], score: 600 }},
    { rank: 2, item: { userName: ['Carla', 'Yuri'], score: 410 }},
    { rank: 3, item: { userName: ['Jompas'], score: 300 } },
    { rank: 4, item: { userName: ['Jonas, Tereza'], score: 266 } },]

I would like to receive the data in this or similar way. I have tried several ways but the code got big and did not work very well, I believe that act some simpler way to solve.

  • Your question seems to have some problems and your experience here in Stack Overflow may not be the best because of this. We want you to do well here and get what you want, but for that we need you to do your part. Here are some guidelines that will help you: Stack Overflow Survival Guide in English.

2 answers

5


You can put the ranks on a set to remove duplicates, convert it into an array and use the map function to generate the result in the format you need in a very elegant and brief way.

let data = [ 
  { rank: 1, item: { userName: 'Rafaela', score: 600 } },
  { rank: 2, item: { userName: 'Carla', score: 410 } },
  { rank: 2, item: { userName: 'Yuri', score: 410 } },
  { rank: 3, item: { userName: 'Jompas', score: 300 } },
  { rank: 4, item: { userName: 'Jonas', score: 266 } },
  { rank: 4, item: { userName: 'Tereza', score: 266 } }]

let result = [...new Set(data.map(x => x.rank))].map( x => {
    return{
        rank: x,
        item : {
            userName : data.filter(d => d.rank == x).map( u => u.item.userName),
            score: data.find(d => d.rank == x).item.score
        }
    }
})

console.log(result)

The secret to aggregating data from userName in an array is to break the logic in two parts.

First you filter the original array by rank using data.filter(d => d.rank == x) that returns an array with all the items of a given rank.

Now that you have this array, just select the userNames and aggregate them into a new array using the method map( u => u.item.userName).

Case the excerpt [...new Set(data.map(x => x.rank))] seem confused, I suggest taking a look at Object Set documentation.

  • I’ll try to follow up and then put the result here.

  • And then you got?

  • Yes man, I followed your example, now I’m studying on websocket to update this ranking in real time.

  • 1

    Show! Anything doubt, put there. You could mark this answer as the correct one, then?

  • Thank you for warning, now that I see you have a symbol to make the answer correct.

2

I managed to implement a code to solve the problem, but not nearly the most optimized and succinct (in my opinion).

But at least you scroll through your array only twice, once in map and another in the filter.

And an important note: the array must be ordered by rank!

let array = [ 
  { rank: 1, item: { userName: 'Rafaela', score: 600 } },
  { rank: 2, item: { userName: 'Carla', score: 410 } },
  { rank: 2, item: { userName: 'Yuri', score: 410 } },
  { rank: 3, item: { userName: 'Jompas', score: 300 } },
  { rank: 4, item: { userName: 'Jonas', score: 266 } },
  { rank: 4, item: { userName: 'Tereza', score: 266 } },
]

let arrayMapeado = array.map((valor, index, elements) => {
  let proximo = elements[index + 1]; // pega o proximo valor da iteração, elements é o array passado no map
  let atual = valor;
  
  if(!proximo) {
    return false; // gera um entrada false, que iremos tratar depois
  }
  
  // Verifica se há scores iguais
  if(atual.item.score === proximo.item.score) {
    let usernameAtual = atual.item.userName;
    let usernameProximo = proximo.item.userName;
    usernameAtual = [usernameAtual, usernameProximo]; // monta o username
    valor.item.userName = usernameAtual;
    elements.splice(index, 1); // Remove o elemento duplicado
    return valor;
  }
  valor.item.userName = [valor.item.userName] // tranforsma o userName em array, caso não tenha entrado no if
  return valor;
});

let arrayNormalizado = arrayMapeado.filter(item => item !== false) // retira o false

console.log(arrayNormalizado);

  • Almost solves my problem, only not solved pq this script deleted an item from the array. Anyway it’s a good start, I’ll check the code and try to make an improvement. Thank you.

  • Which part do you say it excludes? Just so I can complement the answer.

  • The last or the first, I know that there is 1 object missing. But I followed another method and solved my problem

Browser other questions tagged

You are not signed in. Login or sign up in order to post.