Reputation: 41
I've been struggling to restructure this particular object;
[
{
"userId": 1,
"name": "Breaker of Sky",
"rank": 1
},
{
"userId": 1,
"name": "Slayer of Mountain",
"rank": 2
},
{
"userId": 1,
"name": "Balthromaw",
"rank": 3
},
{
"userId": 1,
"name": "Death",
"rank": -1
},
{
"userId": 3,
"name": "Breaker of Sky",
"rank": 2
},
{
"userId": 3,
"name": "Slayer of Mountain",
"rank": 3
},
{
"userId": 3,
"name": "Balthromaw",
"rank": 1
},
{
"userId": 3,
"name": "Death",
"rank": -1
},
{
"userId": 4,
"name": "Breaker of Sky",
"rank": 3
},
{
"userId": 4,
"name": "Slayer of Mountain",
"rank": 2
},
{
"userId": 4,
"name": "Balthromaw",
"rank": 1
},
{
"userId": 4,
"name": "Death",
"rank": -1
},
{
"userId": 8,
"name": "Breaker of Sky",
"rank": 2
},
{
"userId": 8,
"name": "Slayer of Mountain",
"rank": 3
},
{
"userId": 8,
"name": "Balthromaw",
"rank": 4
},
{
"userId": 8,
"name": "Death",
"rank": 1
}
]
to make it look like this object below.
[
{ ranking: [['Death'], ['Breaker of Sky'], ['Slayer of Mountain'], ['Balthromaw']], count: 2 },
{ ranking: [['Death'], ['Balthromaw'], ['Breaker of Sky'], ['Slayer of Mountain']], count: 1 },
{ ranking: [['Death'], ['Balthromaw'], ['Slayer of Mountain'], ['Breaker of Sky']], count: 1 },
]
To simply explain the process, we first need to look for the userId's and group the names with ranks which have same userId's. Then it should line up the names by looking their ranks (-1 will always be at the first place). After that, we should look for the sequence, count it and write down. As an example, this sequence, [['Death'], ['Breaker of Sky'], ['Slayer of Mountain'], ['Balthromaw']]
, has been found 2 times and therefore count is 2.
I would appreciate your help regarding this problem.
My code:
Here is what I have done so far. It's still missing the lining up part of the names by sorting ranks and also values of the ranking property are not arrays. Additionally, I couldn't do the count of sequence part too. Could you help me out with it?
const merged = data.reduce((r, { userId, ...rest }) => {
const key = `${userId}`;
r[key] = r[key] || { ranking: [] };
r[key]['ranking'].push(rest);
return r;
}, {});
const rankArray = Object.values(merged);
console.log(rankArray);
The output I get:
[
{
"ranking": [
{
"name": "Breaker of Sky",
"rank": 1
},
{
"name": "Slayer of Mountain",
"rank": 2
},
{
"name": "Balthromaw",
"rank": 3
},
{
"name": "Death",
"rank": -1
}
]
},
{
"ranking": [
{
"name": "Breaker of Sky",
"rank": 2
},
{
"name": "Slayer of Mountain",
"rank": 3
},
{
"name": "Balthromaw",
"rank": 1
},
{
"name": "Death",
"rank": -1
}
]
},
{
"ranking": [
{
"name": "Breaker of Sky",
"rank": 3
},
{
"name": "Slayer of Mountain",
"rank": 2
},
{
"name": "Balthromaw",
"rank": 1
},
{
"name": "Death",
"rank": -1
}
]
},
{
"ranking": [
{
"name": "Breaker of Sky",
"rank": 2
},
{
"name": "Slayer of Mountain",
"rank": 3
},
{
"name": "Balthromaw",
"rank": 4
},
{
"name": "Death",
"rank": 1
}
]
}
]
Upvotes: 3
Views: 62
Reputation: 57115
There's a few steps to do:
userId
, which you've already done.rank
.count > 1
in the map. (I think this is the logic you want; if it isn't, you can remove the delete byUser[userId]
line)Here's one approach to all of this:
const data = [ { "userId": 1, "name": "Breaker of Sky", "rank": 1 }, { "userId": 1, "name": "Slayer of Mountain", "rank": 2 }, { "userId": 1, "name": "Balthromaw", "rank": 3 }, { "userId": 1, "name": "Death", "rank": -1 }, { "userId": 3, "name": "Breaker of Sky", "rank": 2 }, { "userId": 3, "name": "Slayer of Mountain", "rank": 3 }, { "userId": 3, "name": "Balthromaw", "rank": 1 }, { "userId": 3, "name": "Death", "rank": -1 }, { "userId": 4, "name": "Breaker of Sky", "rank": 3 }, { "userId": 4, "name": "Slayer of Mountain", "rank": 2 }, { "userId": 4, "name": "Balthromaw", "rank": 1 }, { "userId": 4, "name": "Death", "rank": -1 }, { "userId": 8, "name": "Breaker of Sky", "rank": 2 }, { "userId": 8, "name": "Slayer of Mountain", "rank": 3 }, { "userId": 8, "name": "Balthromaw", "rank": 4 }, { "userId": 8, "name": "Death", "rank": 1 } ];
const byUser = data.reduce((a, e) => {
a[e.userId] = a[e.userId] || [];
a[e.userId].push(e);
return a;
}, {});
const counts = {};
for (const [userId, ranking] of Object.entries(byUser)) {
ranking.sort((a, b) => a.rank - b.rank);
byUser[userId] = ranking.map(e => e.name);
const k = byUser[userId];
counts[k] = ++counts[k] || 1;
if (counts[k] > 1) {
delete byUser[userId];
}
}
const result = Object.values(byUser).map(v => ({
ranking: v,
count: counts[v],
}));
console.log(result);
Upvotes: 1