How to push items in JSON Object array in react? - arrays

I have my REACT JS client side and using PHP APIs to fetch data. Im fetching the JSON Object array from API call, in the following format:
{
"records": {
"Master Automotives": [
{
"SparePartID": "43",
"Name": "Oil and Lubricants",
"Price": "4500",
"VendorID": "48",
"CompanyName": "Master Automotives"
},
{
"SparePartID": "45",
"Name": "Lights",
"Price": "2300",
"VendorID": "48",
"CompanyName": "Master Automotives"
}
],
"Repair Solutions": [
{
"SparePartID": "47",
"Name": "Steering Wheel",
"Price": "1500",
"VendorID": "60",
"CompanyName": "Repair Solutions"
}
],
"FiveStar Automotives": [
{
"SparePartID": "51",
"Name": "Brakes",
"Price": "234",
"VendorID": "70",
"CompanyName": "FiveStar Automotives"
},
{
"SparePartID": "53",
"Name": "Clutch",
"Price": "999",
"VendorID": "70",
"CompanyName": "FiveStar Automotives"
},
{
"SparePartID": "55",
"Name": "LED",
"Price": "288",
"VendorID": "70",
"CompanyName": "FiveStar Automotives"
}
]
}
}
From API response, I want to save the above response data (NAME and PRICE) in this.state of myrecords[] (which is empty initially) Plus I also want to push some more items to this above JSON, like for each SPAREPART I want to add "Quantity" and "TotalPrice" items for each data.
Im trying to use .push method to add these Quantity & TotalPrice for each data item. here is my REACT API call where I m fetching data and saving it by setState of myrecords[] and pushing more items in it but IT DOESN'T WORK and shows ERROR msg. please HELP ME how to PUSH the items correctly.
axios.post('http://localhost/Auth/api/customers/show_cart.php', arr,
{
headers: {'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'}
} )
.then(response => {
console.log(response.data.records);
let myItems = [];
response.data.records.forEach((item) => {
myItems.push({SparePartID: item.SparePartID,
Name: item.Name,
Price: item.Price,
Quantity: 1,
totalPrice: item.Price});
})
this.setState({
myrecords: myItems
})
})
.catch(error => {
if (error) {
console.log("REACT Error. Cannot show cart items"); }
});

You can convert your object to array and foreach it
let myItems = [];
let result = Object.entries(response.records).map(( [k, v] ) => ({ [k]: v }));
result.forEach((item) => {
var key = Object.keys(item)[0];
item[key].forEach((sub)=>{
myItems.push({SparePartID: sub.SparePartID,
Name: sub.Name,
Price: sub.Price,
Quantity: 1,
totalPrice: sub.Price});
})
});
let response = {
"records": {
"Master Automotives": [
{
"SparePartID": "43",
"Name": "Oil and Lubricants",
"Price": "4500",
"VendorID": "48",
"CompanyName": "Master Automotives"
},
{
"SparePartID": "45",
"Name": "Lights",
"Price": "2300",
"VendorID": "48",
"CompanyName": "Master Automotives"
}
],
"Repair Solutions": [
{
"SparePartID": "47",
"Name": "Steering Wheel",
"Price": "1500",
"VendorID": "60",
"CompanyName": "Repair Solutions"
}
],
"FiveStar Automotives": [
{
"SparePartID": "51",
"Name": "Brakes",
"Price": "234",
"VendorID": "70",
"CompanyName": "FiveStar Automotives"
},
{
"SparePartID": "53",
"Name": "Clutch",
"Price": "999",
"VendorID": "70",
"CompanyName": "FiveStar Automotives"
},
{
"SparePartID": "55",
"Name": "LED",
"Price": "288",
"VendorID": "70",
"CompanyName": "FiveStar Automotives"
}
]
}
}
let myItems = [];
let result = Object.entries(response.records).map(( [k, v] ) => ({ [k]: v }));
result.forEach((item) => {
var key = Object.keys(item)[0];
item[key].forEach((sub)=>{
myItems.push({SparePartID: sub.SparePartID,
Name: sub.Name,
Price: sub.Price,
Quantity: 1,
totalPrice: sub.Price});
})
});
console.log(myItems);

Related

MongoDB $push in Array of Array Error: No value exists in scope for the shorthand property 'elements'

I wish to add data into Elements but get error. How to solve this mongodb/typescript problem?
Attempt 1 Error: No value exists in scope for the shorthand property 'elements'. Either declare one or provide an initializer.ts(18004)
Attempt 1
async add<T extends { id: string; parentID: string, elementNum: number, name: string, link: string}>(collectionName: string, args: T) {
const db = await this.getDB();
const collection = db.collection(collectionName);
return new Promise((resolve, reject) => {
collection.updateOne({ id: args.id }, {$push: {elements[args.elementNum]: {id: uuid(), name: args.name, link: args.link, elements: [] }}}, (err, res) => {
if (err) {
reject(err);
}
resolve(res);
});
});
}
Attempt 2
changed the following
collection.updateOne({ id: args.id }, {$push: {elements: {id: uuid(), name: args.name, link: args.link, elements: [] }}},
Attempt 2 results in Null added in the end
{
"id": "1",
"name": "wk1",
"iconFile": "icon.png",
"elements": [
[
{
"id": "2",
"name": "element2",
"link": "https",
"elements": [
{
"id": "1",
"name": "element1",
"link": "https:"
}
]
}
],
[
{
"id": "3",
"name": "element3",
"link": "https://",
"elements": [
{
"id": "4",
"name": "w",
"link": "http:/"
}
]
}
],
[
{
"id": "3",
"name": "element3",
"link": "https://",
"elements": [
{
"id": "4",
"name": "w",
"link": "http://"
}
]
},
{
"id": "3",
"name": "element3",
"link": "https://",
"elements": [
{
"id": "4",
"name": "w",
"link": "http://www."
}
]
}
],
null,
]
}
What I want to achieve is the following
{
"id": "1",
"name": "wk1",
"iconFile": "icon.png",
"elements": [
[
{
"id": "2",
"name": "element2",
"link": "https",
"elements": [
{
"id": "1",
"name": "element1",
"link": "https:"
}
]
},
{
"id": "newid",
"name": "newname",
"link": "newlink"
"elements":[]
}
],
[
{
"id": "3",
"name": "element3",
"link": "https://",
"elements": [
.......
]
}
Demo - https://mongoplayground.net/p/Dnmg3lL2891
Use - $[]
The all positional operator $[] indicates that the update operator
should modify all elements in the specified array field.
The $[] operator has the following form:
{ <update operator>: { "<array>.$[]" : value } }
db.collection.update({ _id: 1, "add.id": "1"},
{ $push: { "add.$[].elements": { id: "3", name: "a", link: "" } } })
Demo to push array instead of object - https://mongoplayground.net/p/dh3NSutIv4-
db.collection.update({ _id: 1, "add.id": "1"},
{ $push: { "add.$[].elements": [{ id: "3", name: "a", link: "" }] } })
const args = {};
args.elementNum = 0;
const update = {
[`add.$[].elements.${args.elementNum}`]: {
a: 1
}
};
console.log(update);
//collection.updateOne({ id: args.id }, update); // use like this

how to map and array inside of an object

So here I have an object that I am trying to map:
var bakery = {
"items":
{
"item":[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter":[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
...
...
...
]
}
}
This is the target outcome
var target = [{
"id": 1, //as an int
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": "all of the batter types as a string",
"ingredients": [],//a copy of all the toppings
"countOfFillings": 0
}];
And here is my mapping function
// creates variable bakeryArray that contains the actual Array inside of Baker var
var bakeryArray = bakery.items.item
// newCakes var invoked map function with the bakeryArray
var newCakes = bakeryArray.map(mapCakes)
function mapCakes(oldCakes) {
let batter = oldCakes.batters.batter
console.log(batter, "batter Logged")
var newCakesObject = {
type: oldCakes.type,
name: oldCakes.name,
ppu: oldCakes.ppu,
batters: batter.type,
ingredients: "ingridients",
countOfFillings: "total number of ingrediensts"
};
return newCakesObject;
};
I am running into problems in getting the Batter, Ingredients, and countOfFillings from the old object into the new one.
The only thing I can think of doing in order to get the batters in the newCakesObject is that I have to create another mapping function for the batter (I put my attempt at that below)? and then invoke that in the mapCakes function under batters? but every time I create another function for that I get an error saying that it's undefined once I call newBatterArray in the console
var newBatterArray = bakeryArray.map(mapBatters)
function mapBatters(oldarray) {
let theBatters = oldarray.batters.batter
console.log(theBatters.type, "we ran")
var newBatters = {
type: theBatters.type
}
return newBatters;
}
To have a much more clear interpretation of your bakery object I have tweaked it a bit
var bakery = {
"items":[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
],
"toppings":[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0002",
"type": "donut",
"name": "Cake",
"ppu": 0.65,
"batters":[
{ "id": "1001", "type": "Regular1" },
{ "id": "1002", "type": "Chocolate1" },
{ "id": "1003", "type": "Blueberry1" },
{ "id": "1004", "type": "Devil's Food1" }
],
"toppings":[
{ "id": "5001", "type": "None1" },
{ "id": "5002", "type": "Glazed1" },
{ "id": "5005", "type": "Sugar1" },
{ "id": "5007", "type": "Powdered Sugar1" },
{ "id": "5006", "type": "Chocolate with Sprinkles1" },
{ "id": "5003", "type": "Chocolate1" },
{ "id": "5004", "type": "Maple1" }
]
},
...
...
...
...
]
}
Now You can iterate through each item and build your target array as follows
var target = [];
// define reducer function for each item in bakery.items
const reduceToTarget = item => {
var obj = {};
obj.id = item.id;
obj.type = item.type;
obj.name = item.name;
obj.ppu = item.ppu;
obj.batters = '';
item.batters.forEach(b => obj.batters+=b.type+'|');
obj.ingredients = item.toppings;
target.push(obj);
}
// Now you can call the reduceToTarget function to get the desired target list/array
bakery.items.forEach(reduceToTarget);
The output for this looks something like this
target = [
{
id: "0001"
type: "donut"
name: "Cake"
ppu: 0.55
batters: "Regular|Chocolate|Blueberry|Devil's Food|",
ingredients : [/* list of ingredients*/]
},
{
id: "0002"
type: "donut"
name: "Cake"
ppu: 0.65
batters: "Regular|Chocolate|Blueberry|Devil's Food|",
ingredients : [/* list of ingredients*/]
}
]
NOTE:
For getting the countOfFillings you can simply call length() function on your ingredients list for any element in target

AngularJS/Angular 2: Restructure the json after getting 'http' response

Current:
[{
"name": "a1",
"category": "C1",
"amount": 10
},
{
"name": "a3",
"category": "C1",
"amount": 30
},
{
"name": "a2",
"category": "C1",
"amount": 20
},
{
"name": "a1",
"category": "C2",
"amount": 100
},
{
"name": "a6",
"category": "C2",
"amount": 600
},
{
"name": "a2",
"category": "C2",
"amount": 200
},
{
"name": "a5",
"category": "C2",
"amount": 500
},
{
"name": "a1",
"category": "C3",
"amount": 1000
},
{
"name": "a3",
"category": "C3",
"amount": 3000
},
{
"name": "a5",
"category": "C3",
"amount": 5000
}
]
convert to:
[
{
"name": "a1",
"C1": 10,
"C2": 100,
"C3": 1000
},
{
"name": "a2",
"C1": 20,
"C2": 200,
"C3": -
},
{
"name": "a3",
"C1": 30,
"C2": -,
"C3": 3000
},
{
"name": "a5",
"C1": -,
"C2": 500,
"C3": 5000
},
{
"name": "a6",
"C1": -,
"C2": 600,
"C3": -
}
]
If you want only the properties that have been passed in (e.g. if there is no C2 for a1, then the mapped a1 will not have a C2 property):
var response = {} //set this equal to your original response, rather than an empty object
var list = {}
var mappedResponse = [];
let mapResponse = () => {
response.forEach(item => {
current = list[item.name] || {};
current.name = item.name;
current[item.category] = item.amount;
list[item.name] = current;
});
Object.keys(list).forEach(key => {
mappedResponse.push(list[key]);
});
return mappedResponse;
}
mapResponse();
If you wanted to explicitly declare something like null for those empty fields, rather than having them be undefined, you could change the forEach to look like this:
response.forEach(item => {
current = list[item.name] || {};
current.name = item.name;
current['C1'] = item.category === 'C1' ? item.amount : current['C1'] || null;
current['C2'] = item.category === 'C2' ? item.amount : current['C2'] || null;
current['C3'] = item.category === 'C3' ? item.amount : current['C3'] || null;
list[item.name] = current;
});
Here is my version!
Please not the output JSON you wanted contains the below line.
"C3": -
I checked whether the JSON is valid or not on JSONLint.com and I got the below error.
Error: Parse error on line 14: ... "C2": 200, "C3": - }, { "name":
----------------------^ Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'
This will make the JSON invalid. So what is suggest is to leave out this property! Please let me know if that is fine?
//starting JSON
var json = [{
"name": "a1",
"category": "C1",
"amount": 10
},
{
"name": "a3",
"category": "C1",
"amount": 30
},
{
"name": "a2",
"category": "C1",
"amount": 20
},
{
"name": "a1",
"category": "C2",
"amount": 100
},
{
"name": "a6",
"category": "C2",
"amount": 600
},
{
"name": "a2",
"category": "C2",
"amount": 200
},
{
"name": "a5",
"category": "C2",
"amount": 500
},
{
"name": "a1",
"category": "C3",
"amount": 1000
},
{
"name": "a3",
"category": "C3",
"amount": 3000
},
{
"name": "a5",
"category": "C3",
"amount": 5000
}
]
var out=[];
var final = [];
//code used to filter out the unique names ["a1", "a2", etc]
for (let a of json){
if(out.indexOf(a.name) === -1){
out.push(a.name);
}
}
//loop through the unique names!
for (let a of out){
var obj = {};
//filter the object for a particular name
for(let j of json.filter(function(x){return x.name===a})){
//merge the objects `category` and `amount` as a object
Object.assign(obj, {[j.category]: j.amount});
}
//finally push it to the final list that is `final`
var temp = {name: a};
Object.assign(temp, obj);
final.push(temp);
}
//console.log the output
console.log(final);

Create a specific json(Hash) from a csv using Ruby

I would appreciate any help trying to create a multi faceted CSV (with header) into a json I can use for a post. Here is csv and JSON format required. Ultimately; I need to create a single location that may have 1, 2, or many fax machines.
csv
ID,Location Name,timezone,code,display,address,city,state,postalcode,country,faxlocation,faxnumber,(in)active
5,Location1,America/Chicago,bu,Building,1313 Mocking Bird Lane,The City,IL,999999,USA,Room 1; Room 2,111111111; 2222222222,active
8,Location2,America/New_York,bu,Building,2626 Humpty Dumpty Lane,Another City,NY,999999,USA,Room 1; Room 2; Room 3,111111111; 2222222222; 3333333333,active
32,Location3,America/Los_Angeles,bu,Building,3939 Big Bird Lane,Last City,CA,999999,USA,Room 1,111111111,active
json
{
"resourceType": "Location",
"id": "5",
"description": "America/Chicago",
"name": "Location1",
"address": {
"address": "1313 Mocking Bird Lane",
"city": "The City",
"state": "IL",
"postalCode": "999999",
"country": "USA"
},
"telecom": [
{
"system": "fax",
"value": "1111111111",
"use": "work",
"extension": [
{
"url": "displayValue",
"valueString": "Room 1"
}
]
},
{
"system": "fax",
"value": "2222222222",
"use": "work",
"extension": [
{
"url": "displayValue",
"valueString": "Room "
}
]
}
],
"status": "active"
}
all requires here
locations = CSV.read(csv)
locations.shift # remove header row
locations.each_index do |index|
faxnumarrat = locations[index][10].to_s.delete(' ').split(';') #Take 10th index and turn it into an array
faxlocarray = locations[index][11].to_s.delete(' ').split(';') #Take 11th index and turn it into an array
# keys = ['loc1','loc2']
# values = ['fax1','fax2']
my_hash = Hash[faxnumarray.zip(faxlocarray)] # Combine locations and fax numbers
my_hash.each do |key, value|
#fax_hash = { 'system' => 'fax', 'value' => key, 'use' => 'work', 'extension' => [{ 'url' => 'automaticSend', 'valueBoolean' => false }, { 'url' => 'displayValue', 'valueString' => value }] } #Build up a hash using k,v. ISSUE: Only creates one fax. Need to put all faxes associated no matter how many per location
end
end
Instead of reading in the entire CSV as an array of arrays, you instead can open
or create a new CSV instance and pass in an option to convert the first line of
into headers into keys to access columns within a row more easily; e.g.
locations = CSV.open(csv, headers: true)
location = locations.first
# => #<CSV::Row "ID":"5" "Location Name":"Location1" "timezone":"America/Chicago" "code":"bu" "display":"Building" "address":"1313 Mocking Bird Lane" "city":"The City" "state":"IL" "postalcode":"999999" "country":"USA" "faxlocation":"Room 1; Room 2" "faxnumber":"111111111; 2222222222" "(in)active":"active">
location["Location Name"]
# => "Location1"
With the headers as keys we can use, we can then build a new Hash object using
those old values, whilst also build a collection they you had started in your
question example
locations = CSV.open(csv, headers: true)
results = locations.map.with_index do |location, index|
faxnumarray = location["faxnumber"].delete(' ').split(';') #Take 10th index and turn it into an array
faxlocarray = location["faxlocation"].delete(' ').split(';') #Take 11th index and turn it into an array
# keys = ['loc1','loc2']
# values = ['fax1','fax2']
my_hash = Hash[faxnumarray.zip(faxlocarray)] # Combine locations and fax numbers
{
"resourceType" => "Location",
"id" => location["ID"],
"description" => location["timezone"],
"name" => location["Location Name"],
"address" => {
"address" => location["address"],
"city" => location["city"],
"state" => location["state"],
"postalCode" => location["postalcode"],
"country" => location["country"]
},
"telecom" => my_hash.map do |key, value|
{
'system' => 'fax',
'value' => key,
'use' => 'work',
'extension' => [
{
'url' => 'automaticSend',
'valueBoolean' => false
},
{
'url' => 'displayValue',
'valueString' => value
}
]
}
end,
"status" => location["(in)active"]
}
end
results.to_json
I reused your code where I could and made the last object (the returned object)
within the map block resemble the requested Hash result object. Using map
instead of each means it
Returns a new array with the results of running block once for every element in enum.
-- Module: Enumerable (Ruby 2_4_0)
This produces the following result
[
{
"resourceType": "Location",
"id": "5",
"description": "America/Chicago",
"name": "Location1",
"address": {
"address": "1313 Mocking Bird Lane",
"city": "The City",
"state": "IL",
"postalCode": "999999",
"country": "USA"
},
"telecom": [
{
"system": "fax",
"value": "111111111",
"use": "work",
"extension": [
{
"url": "automaticSend",
"valueBoolean": false
},
{
"url": "displayValue",
"valueString": "Room 1"
}
]
},
{
"system": "fax",
"value": "2222222222",
"use": "work",
"extension": [
{
"url": "automaticSend",
"valueBoolean": false
},
{
"url": "displayValue",
"valueString": " Room 2"
}
]
}
],
"status": "active"
},
{
"resourceType": "Location",
"id": "8",
"description": "America/New_York",
"name": "Location2",
"address": {
"address": "2626 Humpty Dumpty Lane",
"city": "Another City",
"state": "NY",
"postalCode": "999999",
"country": "USA"
},
"telecom": [
{
"system": "fax",
"value": "111111111",
"use": "work",
"extension": [
{
"url": "automaticSend",
"valueBoolean": false
},
{
"url": "displayValue",
"valueString": "Room 1"
}
]
},
{
"system": "fax",
"value": "2222222222",
"use": "work",
"extension": [
{
"url": "automaticSend",
"valueBoolean": false
},
{
"url": "displayValue",
"valueString": " Room 2"
}
]
},
{
"system": "fax",
"value": "3333333333",
"use": "work",
"extension": [
{
"url": "automaticSend",
"valueBoolean": false
},
{
"url": "displayValue",
"valueString": " Room 3"
}
]
}
],
"status": "active"
},
{
"resourceType": "Location",
"id": "32",
"description": "America/Los_Angeles",
"name": "Location3",
"address": {
"address": "3939 Big Bird Lane",
"city": "Last City",
"state": "CA",
"postalCode": "999999",
"country": "USA"
},
"telecom": [
{
"system": "fax",
"value": "111111111",
"use": "work",
"extension": [
{
"url": "automaticSend",
"valueBoolean": false
},
{
"url": "displayValue",
"valueString": "Room 1"
}
]
}
],
"status": "active"
}
]
References:
Class: CSV (Ruby 2_4_0)

How can I get unique array from a collection of nested objects with lodash?

I have the following collection:
"items": [{
"id": 1,
"title": "Montrachet",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [
{"description" : "Kırmızı Şaraplar Desc"},
{"region" :"Bordeaux"},
{"age": "16"},
{"producer" :"Kayra"},
{"grapeType":"Espadeiro"}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999"
},
{
"id": 2,
"title": "Montrachet2",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [
{"description" : "Kırmızı Şaraplar Desc"},
{"region" :"Bordeaux"},
{"age": "16"},
{"producer" :"Kayra"},
{"grapeType":"Chardonnay"}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999",
}
]
I want to grab unique grapeTypes from that collection. The returning array shold be ["Chardonnay","Espadeiro"]
What is the best way to do it with lodash?
I think this combination of pluck, map and filter should do it:
var result = _.chain(obj.items).pluck('properties').map(function(obj) {
return _.filter(obj, function(prop) {
return prop.grapeType;
})[0].grapeType;
}).uniq().value();
console.log(result);
Check the demo run below.
// Code goes here
var obj = {
items: [{
"id": 1,
"title": "Montrachet",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [{
"description": "Kırmızı Şaraplar Desc"
}, {
"region": "Bordeaux"
}, {
"age": "16"
}, {
"producer": "Kayra"
}, {
"grapeType": "Espadeiro"
}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999"
},
{
"id": 2,
"title": "Montrachet2",
"imageUrl": "http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"imageUrls": [
"http://winebuff.com.hk/products_image/3376-Ramonet-ChassagneMontrachetBlanc.jpg",
"http://media.riepenau.com/wines/17973_b.jpg",
"http://lorempixel.com/400/400/food/3"
],
"properties": [{
"description": "Kırmızı Şaraplar Desc"
}, {
"region": "Bordeaux"
}, {
"age": "16"
}, {
"producer": "Kayra"
}, {
"grapeType": "Chardonnay"
}
],
"priceGlass": "1",
"priceBottle": "2",
"year": "1999",
}
]
};
var result = _.chain(obj.items).pluck('properties').map(function(obj) {
return _.filter(obj, function(prop) {
return prop.grapeType;
})[0].grapeType;
}).uniq().value();
document.write(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.8.0/lodash.js"></script>
UPD. If grapeType can be missing from properties then the script should be
var result = _.chain(obj.items).pluck('properties').map(function(obj) {
return (_.filter(obj, function(prop) {
return prop.grapeType;
})[0] || {}).grapeType;
}).compact().uniq().value();
Here's one way to do it with lodash:
_(items)
.pluck('properties')
.map(function(item) {
return _.find(item, _.ary(_.partialRight(_.has, 'grapeType'), 1));
})
.pluck('grapeType')
.uniq()
.value();
First, you get the properties arrays using pluck(). Next, you use find() to get the first object in this array that has a grapeType property. This is done using has(), and partially-applying the argument to build the callback function.
Next, you use pluck() again to get the actual property values. Finally, uniq() ensures there are no duplicates.

Resources