Reputation: 121
I have data in the below format
{
games: [{id: "1", category_name: "Men Age above 18", game: "Running 100 Mtrs", isActive: "1"}, {
id: "2",
category_name: "Men Age above 18",
game: "Running 200 Mtrs",
isActive: "1"
}, {id: "3", category_name: "Men Age above 18", game: "Running 400 Mtrs", isActive: "1"}, {
id: "4",
category_name: "Men Age above 18",
game: "Long Jump",
isActive: "1"
}, {id: "5", category_name: "Men Age above 18", game: "Tug of War (Team)", isActive: "1"}, {
id: "6",
category_name: "Women Age above 18",
game: "Rangoli",
isActive: "1"
}, {id: "7", category_name: "Women Age above 18", game: "Kho Kho (Team)", isActive: "1"}]
}
I want the data to be organized the way below:
gameGroups = {
'Men Age above 18': ['Running 100 Mtrs', 'Running 200 Mtrs', 'Running 400 Mtrs', 'Long Jump', 'Tug of War (Team)'],
'Women Age above 18': ['Rangoli', 'Kho Kho (Team)']
}
I got the result with the below code:
gameGroups = {};
cat_array = [];
for (i = 0; i < data['games'].length; i++) {
gameGroups[data['games'][i]['category_name']] = [];
}
for (var key in gameGroups) {
cat_array = [];
for (i = 0; i < data['games'].length; i++) {
if (data['games'][i]['category_name'] === key)
cat_array.push(data['games'][i]['game'])
}
if (gameGroups.hasOwnProperty(key)) {
gameGroups[key] = cat_array;
}
}
The above code is valid but lengthy.
Can there be some other method to do this in an easier way?
Upvotes: 0
Views: 69
Reputation: 136
You can use forEach and ternary expression (or use if's instead):
const data = {
games: [{id: "1", category_name: "Men Age above 18", game: "Running 100 Mtrs", isActive: "1"}, {
id: "2",
category_name: "Men Age above 18",
game: "Running 200 Mtrs",
isActive: "1"
}, {id: "3", category_name: "Men Age above 18", game: "Running 400 Mtrs", isActive: "1"}, {
id: "4",
category_name: "Men Age above 18",
game: "Long Jump",
isActive: "1"
}, {id: "5", category_name: "Men Age above 18", game: "Tug of War (Team)", isActive: "1"}, {
id: "6",
category_name: "Women Age above 18",
game: "Rangoli",
isActive: "1"
}, {id: "7", category_name: "Women Age above 18", game: "Kho Kho (Team)", isActive: "1"}]
};
let gameGroups = {};
data.games.forEach(gameObject => {
let categoryName = gameObject.category_name;
gameGroups[categoryName] && !gameGroups[categoryName].includes(gameObject.game) ?
gameGroups[categoryName].push(gameObject.game) : gameGroups[categoryName] = [gameObject.game]
});
console.log(gameGroups);
Upvotes: 0
Reputation: 8589
This can be done very shortly inline as the other answers show. But since I'm faced with this exact transformation often, I made an utility function that can do these kind of transformations. It's a bit longer than a solution to only this specific problem, but can be used for a lot of different transformations as well.
const data = {
games: [
{
id: "1",
category_name: "Men Age above 18",
game: "Running 100 Mtrs",
isActive: "1"
},
{
id: "2",
category_name: "Men Age above 18",
game: "Running 200 Mtrs",
isActive: "1"
},
{
id: "3",
category_name: "Men Age above 18",
game: "Running 400 Mtrs",
isActive: "1"
},
{
id: "4",
category_name: "Men Age above 18",
game: "Long Jump",
isActive: "1"
},
{
id: "5",
category_name: "Men Age above 18",
game: "Tug of War (Team)",
isActive: "1"
},
{
id: "6",
category_name: "Women Age above 18",
game: "Rangoli",
isActive: "1"
},
{
id: "7",
category_name: "Women Age above 18",
game: "Kho Kho (Team)",
isActive: "1"
}
]
};
/** prop_hash => reduce an array into an object, using property reference or functions to create the keys and values.
* @type Public Function
* @name prop_hash
* @param String || Function property_reference
* => String: name of a property on the item that will become the key.
* => Function: takes in the item, should return a string that will become the key.
* @param Boolean is_unique
* => If set to true, the item will be the only result using that key.
* => If set to false, the key will be an array the item gets pushed into.
* @param Function transformation_value
* => Takes in the item, should return the value we want to use for the key.
* @returns Object
* @notes
* => By adding keys to the object we reduce into, we can ensure a key exists
* even if no items inside the collection would return that key.
*/
const prop_hash = ( key_reference, is_unique, transformation_value ) => {
const is_str = Object.prototype.toString.call( key_reference ) === '[object String]';
const generateKey = is_str
? item => item[ key_reference ]
: ( item, index, source ) => key_reference( item, index, source );
return ( hash, item, index, source ) => {
const key = generateKey( item, index, source );
if ( key && !hash.hasOwnProperty( key ) ) {
if ( is_unique ) hash[ key ] = transformation_value ? transformation_value( item, index, source ) : item;
else hash[ key ] = [];
}
if ( !is_unique ) hash[ key ].push( transformation_value ? transformation_value( item, index, source ): item );
return hash;
};
};
const result = data.games.reduce( prop_hash( 'category_name', false, item => item.game ), {});
console.log( result );
Upvotes: 0
Reputation: 35202
You can shorten your for loop. If the current category_name
already exists, add the current game
to that array. Else, Add category_name
as key to gameGroups
with a new array.
var data = {games:[{id:"1",category_name:"Men Age above 18",game:"Running 100 Mtrs",isActive:"1"},{id:"2",category_name:"Men Age above 18",game:"Running 200 Mtrs",isActive:"1"},{id:"3",category_name:"Men Age above 18",game:"Running 400 Mtrs",isActive:"1"},{id:"4",category_name:"Men Age above 18",game:"Long Jump",isActive:"1"},{id:"5",category_name:"Men Age above 18",game:"Tug of War (Team)",isActive:"1"},{id:"6",category_name:"Women Age above 18",game:"Rangoli",isActive:"1"},{id:"7",category_name:"Women Age above 18",game:"Kho Kho (Team)",isActive:"1"}]};
var gameGroups = {},
games = data['games'];
for (var i = 0; i < games.length; i++) {
var game = games[i];
if (gameGroups[game.category_name])
gameGroups[game.category_name].push(game.game)
else
gameGroups[game.category_name] = [game.game]
}
console.log(gameGroups)
Or, you could reduce
the array. Destructure the parameter to get category_name
and game
properties from each object. Then add each category to the accumulator as key and an array of games
as it's value.
const input = {games:[{id:"1",category_name:"Men Age above 18",game:"Running 100 Mtrs",isActive:"1"},{id:"2",category_name:"Men Age above 18",game:"Running 200 Mtrs",isActive:"1"},{id:"3",category_name:"Men Age above 18",game:"Running 400 Mtrs",isActive:"1"},{id:"4",category_name:"Men Age above 18",game:"Long Jump",isActive:"1"},{id:"5",category_name:"Men Age above 18",game:"Tug of War (Team)",isActive:"1"},{id:"6",category_name:"Women Age above 18",game:"Rangoli",isActive:"1"},{id:"7",category_name:"Women Age above 18",game:"Kho Kho (Team)",isActive:"1"}]};
const output = input.games.reduce((acc, { category_name, game }) => {
acc[category_name] = acc[category_name] || [];
acc[category_name].push(game)
return acc;
}, {})
console.log(output)
Upvotes: 3
Reputation: 2099
let's say that the initial object is called gamesList:
let gamesGroup = [];
for(let game of gamesList) {
let index = gamesGroup.findIndex(el => el.category_group === game.category_group);
if (index !== -1) {
let element = gamesGroup[index];
element.games.push(game.game);
}
else {
gamesGroup.push({game_category: game.game_category, games: [game.game]});
}
}
Upvotes: 0