Rahul Kalidindi
Rahul Kalidindi

Reputation: 4736

Forming JSON with Key and Value if Key Exists

I have a JSON Structure something like:

    [  
   {  
      "name":"angelinas"
   },
   {  
      "name":"besuto"
   },
   {  
      "name":"catch",
      "cuisine":"Japanese"
   },
   {  
      "name":"center cut"
   },
   {  
      "name":"fedora"
   },
   {  
      "name":"Habanero",
      "cuisine":"Mexican"
   },
   {  
      "name":"Indies"
   },
   {  
      "name":"new"
   },
   {  
      "name":"RazINN"
   },
   {  
      "name":"restaurantTestVenue779"
   },
   {  
      "name":"restaurantTestVenue9703"
   },
   {  
      "name":"Salsa ",
      "cuisine":"Mexican"
   },
   {  
      "name":"Sushi Place",
      "cuisine":"Japanese"
   },
   {  
      "name":"The Ashoka"
   },
   {  
      "name":"The Poboys"
   },
   {  
      "name":"the shogun"
   },
   {  
      "name":"vinyard view"
   }
]

Using the JSON above i want to identify whether a cuisine is assosiated to restaurant. If yes, I want to build a JSON Structure something like:

[  
   {  
      "Mexican":{  
         "venueNames":[  
            "Habanero",
            "Salsa"
         ]
      }
   },
   {  
      "Japanese":{  
         "venueNames":[  
            "Sushi Place",
            "catch"
         ]
      }
   }
]

Have tried to build the JSON using a for loop and .hasProperty but not much of a success.

Upvotes: 0

Views: 897

Answers (4)

Get Off My Lawn
Get Off My Lawn

Reputation: 36311

Using a few es6 features, we can generate this list with Set, map and filter.

We will first map a list of cuisines, and remove invalid ones such as undefined. With that we will use a Set to create a unique list of cuisines.

Next we will take that list and map it again to return the final object, by filtering the original object where the cuisine matches the current iteration. Finally we map the filtered results to return just the name to the venueNames object.

Our result will look like this:

function getItems(places) {
  // Get a unique list of cuisines
  return [...new Set(places.map(p => p.cuisine).filter(c => c))]
    // Build the result
    .map(c => {
      return {
        [c]: {
          // Get a list of cuisines that match the current cuisine
          venueNames: places.filter(p => p.cuisine == c).map(c => c.name)
        }
      }
    })
}

const places = [
  {"name": "angelinas"},
  {"name": "besuto"},
  {"name": "catch","cuisine": "Japanese"},
  {"name": "center cut"},
  {"name": "fedora"},
  {"name": "Habanero","cuisine": "Mexican"},
  {"name": "Indies"},
  {"name": "new"},
  {"name": "RazINN"},
  {"name": "restaurantTestVenue779"},
  {"name": "restaurantTestVenue9703"},
  {"name": "Salsa ","cuisine": "Mexican"},
  {"name": "Sushi Place","cuisine": "Japanese"},
  {"name": "The Ashoka"},
  {"name": "The Poboys"},
  {"name": "the shogun"},
  {"name": "vinyard view"}
]

console.log(getItems(places))

Upvotes: 0

daremachine
daremachine

Reputation: 2788

You can use in one loop below.

data.forEach(function(item) {
    // if item has cuisine and cuisine not exist in new array
    if(item["cuisine"] != null && typeof newArr.find(v => v[item.cuisine] != null) == 'undefined') {
    // create new object with structure
    let obj = {};
    obj[item.cuisine] = {
         "venueNames":[item.name]
      };

    newArr.push(obj);
  }
  else {
    // else find existing cuisine and add new venue
    let obj = newArr.find(v => v.hasOwnProperty(item.cuisine));
    if(typeof obj != 'undefined') {
        obj[item.cuisine].venueNames.push(item.name);
    }
  }
});

JSFIDDLE

Upvotes: 0

Shilly
Shilly

Reputation: 8589

It's a simple reduction of the array. If the restaurant has a defined cuisine, check if the result already has this cuisine defined. If not, create an object for it where you can push the restaurant name to.

const restaurants = [
   {  
    "name":"angelinas"
   },
   {  
    "name":"besuto"
   },
   {  
    "name":"catch",
    "cuisine":"Japanese"
   },
   {  
    "name":"center cut"
   },
   {  
    "name":"fedora"
   },
   {  
    "name":"Habanero",
    "cuisine":"Mexican"
   },
   {  
    "name":"Indies"
   },
   {  
    "name":"new"
   },
   {  
    "name":"RazINN"
   },
   {  
    "name":"restaurantTestVenue779"
   },
   {  
    "name":"restaurantTestVenue9703"
   },
   {  
    "name":"Salsa ",
    "cuisine":"Mexican"
   },
   {  
    "name":"Sushi Place",
    "cuisine":"Japanese"
   },
   {  
    "name":"The Ashoka"
   },
   {  
    "name":"The Poboys"
   },
   {  
    "name":"the shogun"
   },
   {  
    "name":"vinyard view"
   }
];
const cuisines = restaurants.reduce((result, restaurant ) => {
  if ( restaurant.hasOwnProperty( 'cuisine' )) {
    const { cuisine } = restaurant;
    if ( !result.hasOwnProperty( cuisine )) {
      result[ cuisine ] = {
        venueNames: []
      };
    }
    result[ cuisine ].venueNames.push( restaurant.name );
  }
  return result;
}, {});
console.log( cuisines );

In my personal opinion, I would use a slightly different structure though. If we represent collections with objects that are always the same, we can simplify most transformations. This is less efficient that doing everything in one loop, but the code used to create the transformation is almost readable english:

const restaurants = [  
   { "name": "angelinas", "cuisine": null },
   { "name": "besuto", "cuisine": null },
   { "name": "catch", "cuisine": "japanese" },
   { "name": "center cut", "cuisine": null },
   { "name": "fedora", "cuisine": null },
   { "name": "habanero", "cuisine": "mexican" },
   { "name": "Indies", "cuisine": null },
   { "name": "new", "cuisine": null },
   { "name": "RazINN", "cuisine": null },
   { "name": "restaurantTestVenue779", "cuisine": null },
   { "name": "restaurantTestVenue9703", "cuisine": null },
   { "name": "Salsa ", "cuisine": "mexican" },
   { "name": "Sushi Place", "cuisine": "japanese" },
   { "name": "The Ashoka", "cuisine": null },
   { "name": "The Poboys", "cuisine": null },
   { "name": "the shogun", "cuisine": null },
   { "name": "vinyard view", "cuisine": null }
];
const create_cuisine = name => ({ name, "venues": [] });
const unique = () => {
  const seen = {};
  return item => {
    const json = JSON.stringify( item );
    return seen.hasOwnProperty( json )
      ? false
      : ( seen[ json ] = true );
  };
};
// Filter away all the restaurants without a cuisine value.
const restaurants_with_cuisine = restaurants.filter( restaurant => restaurant.cuisine );		
const cuisines = restaurants_with_cuisine
  // Extract the cuisine anmes from the restaurants.
  .map( restaurant => restaurant.cuisine )
  // Filter aways all the duplicates.
  .filter( unique() )
  // Create a new cuisine object.
  .map( cuisine_name => create_cuisine( cuisine_name ));
// Finally add all the restaurant names to the right cuisine.
restaurants_with_cuisine.forEach( restaurant => cuisines.find( cuisine => cuisine.name === restaurant.cuisine ).venues.push( restaurant.name ));

console.log( cuisines );

Upvotes: 0

Siyavash
Siyavash

Reputation: 980

Here is what you can do! First iterate through the data and use the method "hasOwnProperty" to check if the cuisine exists and if it does then check if your cuisines object has that cuisine and if does then add it to it.

const data = [{
        "name": "angelinas"
    },
    {
        "name": "besuto"
    },
    {
        "name": "catch",
        "cuisine": "Japanese"
    },
    {
        "name": "center cut"
    },
    {
        "name": "fedora"
    },
    {
        "name": "Habanero",
        "cuisine": "Mexican"
    },
    {
        "name": "Indies"
    },
    {
        "name": "new"
    },
    {
        "name": "RazINN"
    },
    {
        "name": "restaurantTestVenue779"
    },
    {
        "name": "restaurantTestVenue9703"
    },
    {
        "name": "Salsa ",
        "cuisine": "Mexican"
    },
    {
        "name": "Sushi Place",
        "cuisine": "Japanese"
    },
    {
        "name": "The Ashoka"
    },
    {
        "name": "The Poboys"
    },
    {
        "name": "the shogun"
    },
    {
        "name": "vinyard view"
    }
]

let cuisines = {};


for (const resturant of data) {
    if (resturant.hasOwnProperty('cuisine')) {

        if (cuisines.hasOwnProperty(resturant.cuisine)) {
            cuisines[resturant.cuisine].venueNames.push(resturant.name);
        } else {
            cuisines[resturant.cuisine] = {
                venueNames: [resturant.name]
            };
        }
    }
}

Upvotes: 1

Related Questions