Santu
Santu

Reputation: 121

Object and Array looping

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

Answers (4)

Evgeni
Evgeni

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

Shilly
Shilly

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

adiga
adiga

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

CodeRonin
CodeRonin

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

Related Questions