Formatting a JSON data using lodash [duplicate] - javascript

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I have a JSON data with the following format:
activities
[
{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
"items": [
{
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}
]
},
{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": [
{
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
},
{
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}
]
},
{
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": [
{
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}
]
}
]
I want to reformat this data using lodash or simply javascript to look like this:
/*poi_id is the key*/
"1": [{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
"items": {
/*due_date is the key*/
"2016-09-08T18:15:00.000Z": [{
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}]
}
}, {
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": {
"2016-09-27T18:15:00.000Z": [{
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}]
}
}],
"9": [{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": {
"2016-09-14T18:15:00.000Z": [{
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
}, {
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}]
}
}]
All I want is to put the data that has the same poi_id under one collection with the key of poi_id and same for the items with same due_date.
Here's what I've done so far:
let activityArray = {};
_.forEach(activities, (activityItem) => {
if (!activityArray[activityItem.poi_id]) {
activityArray[activityItem.poi_id] = [];
}
activityArray[activityItem.poi_id].push(activityItem);
_.forEach(activityArray[activityItem.poi_id], (value, key) => {
activityArray[activityItem.poi_id][key].items.unshift(activityArray[activityItem.poi_id][key].due_date);
});
});
And this is what I got:
"1": [{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
/*unShift added due_date twice here, I want here key value pair*/
"items": [
"2016-09-08T18:15:00.000Z",
"2016-09-08T18:15:00.000Z", {
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}
]
}, {
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": [
"2016-09-27T18:15:00.000Z", {
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}
]
}],
"9": [{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": [
"2016-09-14T18:15:00.000Z", {
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
}, {
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}
]
}]
I tried with other approaches too, but couldn't make it like the one I'm expecting.
Please guide me here.
Thanks.

A compact solution in plain Javascript with an object as hash for the items arrays.
var activities = [{ "id": 32, "poi_id": 1, "due_date": "2016-09-08T18:15:00.000Z", "items": [{ "id": 21, "name": "Choluv jar : JAR", "activity_id": 32 }] }, { "id": 30, "poi_id": 9, "due_date": "2016-09-14T18:15:00.000Z", "items": [{ "id": 17, "name": "Bourbon Family : PKT", "activity_id": 30 }, { "id": 18, "name": "Choluv jar : JAR", "activity_id": 30 }] }, { "id": 29, "poi_id": 1, "due_date": "2016-09-27T18:15:00.000Z", "items": [{ "id": 16, "name": "Choluv jar : JAR", "activity_id": 29 }] }],
hash = {},
grouped = {};
activities.forEach(a => {
hash[a.poi_id] = hash[a.poi_id] || {};
hash[a.poi_id][a.due_date] = hash[a.poi_id][a.due_date] || [];
grouped[a.poi_id] = grouped[a.poi_id] || [];
grouped[a.poi_id].push({
id: a.id,
poi_id: a.poi_id,
due_date: a.due_date,
items: { [a.due_date]: hash[a.poi_id][a.due_date] }
});
a.items.forEach(b => hash[a.poi_id][a.due_date].push(b));
});
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Find corresponding product combination according to user's selection

This corresponds to an ecommerce site.
I have the following JSON corresponding to a list of combinations (sizes, colors, etc) valid for a certain product:
[
{
"id": 7,
"price": 12,
"stock": 100,
"options": [
{
"attribute_value_id": 3,
"attribute_value_name": "Blue",
"attribute_id": 1,
"attribute_name": "Colores",
"disabled": false,
"attribute": [
{
"id": 1,
"name": "Colores"
}
]
},
{
"attribute_value_id": 32,
"attribute_value_name": "M",
"attribute_id": 4,
"attribute_name": "Talla Superior",
"disabled": false,
"attribute": [
{
"id": 4,
"name": "Talla Superior"
}
]
}
]
},
{
"id": 17,
"price": 7.2,
"stock": 12,
"options": [
{
"attribute_value_id": 2,
"attribute_value_name": "Cream",
"attribute_id": 1,
"attribute_name": "Colores",
"disabled": false,
"attribute": [
{
"id": 1,
"name": "Colores"
}
]
},
{
"attribute_value_id": 38,
"attribute_value_name": "XL",
"attribute_id": 4,
"attribute_name": "Talla Superior",
"disabled": false,
"attribute": [
{
"id": 4,
"name": "Talla Superior"
}
]
}
]
},
{
"id": 20,
"price": 528,
"stock": 44,
"options": [
{
"attribute_value_id": 8,
"attribute_value_name": "Purple",
"attribute_id": 1,
"attribute_name": "Colores",
"disabled": false,
"attribute": [
{
"id": 1,
"name": "Colores"
}
]
},
{
"attribute_value_id": 29,
"attribute_value_name": "S",
"attribute_id": 4,
"attribute_name": "Talla Superior",
"disabled": false,
"attribute": [
{
"id": 4,
"name": "Talla Superior"
}
]
}
]
},
{
"id": 21,
"price": 401,
"stock": 37,
"options": [
{
"attribute_value_id": 3,
"attribute_value_name": "Blue",
"attribute_id": 1,
"attribute_name": "Colores",
"disabled": false,
"attribute": [
{
"id": 1,
"name": "Colores"
}
]
},
{
"attribute_value_id": 35,
"attribute_value_name": "L",
"attribute_id": 4,
"attribute_name": "Talla Superior",
"disabled": false,
"attribute": [
{
"id": 4,
"name": "Talla Superior"
}
]
}
]
}
]
I require the following: if the user indicates that he wants the product in color "Blue" and size "L" (ids 3 and 35 respectively) based on this array look for which option has both features so that I can then know what stock and price there is for that combination.
I can't find how to do that in JavaScript/Typescript.
Thank you in advance.
U can do something like this.
const found = data.find(
(item) =>
item.options[0].attribute_value_name === 'Blue' &&
item.options[1].attribute_value_name === 'L'
);
console.log(found && found.price);

Array object grouping in JavaScript

I need to convert below unformatted JSON format into formatted input. We need to find id's similar to parent id for different items inside array element of object and then need to push it into children to that id. Below is my code that needs to transform
Input
{
"0": [
{
"id": 10,
"title": "House",
"level": 0,
"children": [],
"parent_id": null
}
],
"1": [
{
"id": 12,
"title": "Red Roof",
"level": 1,
"children": [],
"parent_id": 10
},
{
"id": 18,
"title": "Blue Roof",
"level": 1,
"children": [],
"parent_id": 10
}
],
"2": [
{
"id": 17,
"title": "Blue Windoww",
"level": 2,
"children": [],
"parent_id": 12
},
{
"id": 16,
"title": "Door",
"level": 2,
"children": [],
"parent_id": 13
}
]
}
Output
[
{
"id": 10,
"title": "House",
"level": 0,
"children": [
{
"id": 12,
"title": "RedRoofff",
"level": 1,
"children": [
{
"id": 17,
"title": "Blue Windoww",
"level": 2,
"children": [],
"parent_id": 12
}
],
"parent_id": 10
},
{
"id": 18,
"title": "Blue Roof",
"level": 1,
"children": [],
"parent_id": 10
},
{
"id": 13,
"title": "Wall",
"level": 1,
"children": [
{
"id": 16,
"title": "Door",
"level": 2,
"children": [],
"parent_id": 13
}
],
"parent_id": 10
}
],
"parent_id": null
}
]
Please find the solution to above problem.
first, we track the node with Id and then we update the children array like this.
(btw, your input have a missing node, 13)
const input = {
"0": [{
"id": 10,
"title": "House",
"level": 0,
"children": [],
"parent_id": null
}, {
"id": 13,
"title": "Wall",
"level": 0,
"children": [],
"parent_id": null
}],
"1": [{
"id": 12,
"title": "Red Roof",
"level": 1,
"children": [],
"parent_id": 10
},
{
"id": 18,
"title": "Blue Roof",
"level": 1,
"children": [],
"parent_id": 10
},
],
"2": [{
"id": 17,
"title": "Blue Windoww",
"level": 2,
"children": [],
"parent_id": 12
},
{
"id": 16,
"title": "Door",
"level": 2,
"children": [],
"parent_id": 13
},
]
};
const results = [];
const mapId2Node = Object.values(input).reduce((acc, vals) => {
vals.forEach(val => {
acc[val.id] = val;
if (val.parent_id === null) {
results.push(val);
}
});
return acc;
}, {});
Object.values(input).forEach(vals => {
vals.forEach(val => {
if (val.parent_id !== null) {
mapId2Node[val.parent_id].children.push(val);
}
});
});
conosle.log(results);

How to get a specific object from whole object?

I am trying to get specific object from a whole object below is the example
by using localStorage.getItem('shop/elasticCache/shirt');
I get below data
{"description":"Tech Shirt","configurable_options":[{"attribute_id":80,"values":[{"value_index":"5176","label":"RUST"}],"label":"Color","attribute_code":"color"},{"attribute_id":125,"values":[{"value_index":"2898","label":"Small"},{"value_index":"2901","label":"Medium"},{"value_index":"2904","label":"Large"}],"label":"Size","attribute_code":"size"}],"tsk":1594790209,"size_options":[2898,2901,2904],"regular_price":28,"final_price":null,"price":28,"color_options":[5176],"special_from_date":null,"id":250659,"category":[{"category_id":2,"name":"Default Category","position":1},{"category_id":3,"name":"Clothing","position":14985},{"category_id":30,"name":"Bottoms","position":798},{"category_id":58,"name":"Leggings","position":1},{"category_id":1130,"name":"Char Test Category","position":30}],"sku":"S155551","product_links":[{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"},{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"}
I am trying to get
{"category_id":3,"name":"Clothing","position":14985},{"category_id":30,"name":"Bottoms","position":798},{"category_id":58,"name":"Leggings","position":1},{"category_id":1130,"name":"Char Test Category","position":30}]
Is their any way it can be done ?
const {category} = JSON.parse(localStorage.getItem('shop/elasticCache/shirt');)
or
const {category } = {
"description": "Tech Shirt",
"configurable_options": [{
"attribute_id": 80,
"values": [{
"value_index": "5176",
"label": "RUST"
}],
"label": "Color",
"attribute_code": "color"
}, {
"attribute_id": 125,
"values": [{
"value_index": "2898",
"label": "Small"
}, {
"value_index": "2901",
"label": "Medium"
}, {
"value_index": "2904",
"label": "Large"
}],
"label": "Size",
"attribute_code": "size"
}],
"tsk": 1594790209,
"size_options": [2898, 2901, 2904],
"regular_price": 28,
"final_price": null,
"price": 28,
"color_options": [5176],
"special_from_date": null,
"id": 250659,
"category": [{
"category_id": 2,
"name": "Default Category",
"position": 1
}, {
"category_id": 3,
"name": "Clothing",
"position": 14985
}, {
"category_id": 30,
"name": "Bottoms",
"position": 798
}, {
"category_id": 58,
"name": "Leggings",
"position": 1
}, {
"category_id": 1130,
"name": "Char Test Category",
"position": 30
}],
"sku": "S155551",
"product_links": [{
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}, {
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}]
}
objc={"description":"Tech Shirt","configurable_options":
[{"attribute_id":80,"values":[{"value_index":"5176","label":"RUST"}],
"label":"Color","attribute_code":"color"},
{"attribute_id":125,"values":[{"value_index":"2898","label":"Small"}
,{"value_index":"2901","label":"Medium"},
{"value_index":"2904","label":"Large"}],
"label":"Size","attribute_code":"size"}],
"tsk":1594790209,"size_options":[2898,2901,2904]
,"regular_price":28,"final_price":null,"price":28,
"color_options":[5176],"special_from_date":null,"id":250659,
"category":[{"category_id":2,"name":"Default Category","position":1},
{"category_id":3,"name":"Clothing","position":14985},
{"category_id":30,"name":"Bottoms","position":798},
{"category_id":58,"name":"Leggings","position":1},
{"category_id":1130,"name":"Char Test Category","position":30}],
"sku":"S155551","product_links":
[{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"},
{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"}]
}
res = objc["category"]
res.shift()
console.log(res)
$(document).ready(function () {
var jsonObj = {
"description": "Tech Shirt",
"configurable_options": [{
"attribute_id": 80,
"values": [{
"value_index": "5176",
"label": "RUST"
}],
"label": "Color",
"attribute_code": "color"
}, {
"attribute_id": 125,
"values": [{
"value_index": "2898",
"label": "Small"
}, {
"value_index": "2901",
"label": "Medium"
}, {
"value_index": "2904",
"label": "Large"
}],
"label": "Size",
"attribute_code": "size"
}],
"tsk": 1594790209,
"size_options": [2898, 2901, 2904],
"regular_price": 28,
"final_price": null,
"price": 28,
"color_options": [5176],
"special_from_date": null,
"id": 250659,
"category": [{
"category_id": 2,
"name": "Default Category",
"position": 1
}, {
"category_id": 3,
"name": "Clothing",
"position": 14985
}, {
"category_id": 30,
"name": "Bottoms",
"position": 798
}, {
"category_id": 58,
"name": "Leggings",
"position": 1
}, {
"category_id": 1130,
"name": "Char Test Category",
"position": 30
}],
"sku": "S155551",
"product_links": [{
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}, {
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}]
};
for(var i = 1; i < jsonObj.category.length; i++){
console.log(jsonObj.category[i]);
}
});
You can iterate through the entire object and can get the required values. The above code gives the values of category from index 1.

Add a property to grouped objects and ungroup

I'm using underscore.js to group my objects, now I want to add a property to work as an identifier for that group and then reduce those objects back into its original structure. But not sure how to do it.
The rule is to find who has more than one appointment in that day and add a property to it.
Something we achieved here:
https://jsfiddle.net/bjxgszmw/
with this line of code:
var resultt = _.chain(allAppointments)
.groupBy('appointment_date')
.mapObject( date => _.groupBy(date, 'email' ) )
So from what we have've got which is this:
{
"23July": {
"john#domain.com": [
{
"ap_id": 23,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning"
},
{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
}
],
"rose#domain.com": [
{
"ap_id": 55,
to something simple like this;
allAppointments_Filtered:
[{
"ap_id": 23,
"name": "John",
"email": "John#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning",
hasMultipleAppointmentOnDate: "yes"
},{
"ap_id": 55,
"name": "Rose",
"email": "rose#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternoon"
hasMultipleAppointmentOnDate: "nope"
},{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternoon"
hasMultipleAppointmentOnDate: "yes"
},{
...
}];
Well, you don't need to do all those grouping and mappings. All you have to do is a single map and a count based on the current appointment you check:
var allAppointments = [
{
"ap_id": 23,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning"
},
{
"ap_id": 55,
"name": "Rose",
"email": "rose#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 70,
"name": "Kate",
"email": "kate#domain.com",
"appointment_date": "29July",
"appointment_category": 4,
"time": "afternon"
}
]
var counts = {};
var result = _.mapObject(allAppointments, (appointment) => {
var key = appointment.email + appointment.appointment_date;
if (!_.has(counts, key)) {
counts[key] = _.countBy(allAppointments, (app) =>
appointment.email === app.email &&
appointment.appointment_date === app.appointment_date
).true > 1
}
appointment.hasMultipleAppointmentOnDate = counts[key];
return appointment;
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
You need to group by a composite key:
// data
const allAppointments = [
{
"ap_id": 23,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning"
},
{
"ap_id": 55,
"name": "Rose",
"email": "rose#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 70,
"name": "Kate",
"email": "kate#domain.com",
"appointment_date": "29July",
"appointment_category": 4,
"time": "afternon"
}
];
// gets grouping key, which is email + date
const groupKey = i => i.email +'_'+ i.appointment_date;
// store counts for appointments for unique (email + date)
const counts = _.countBy(allAppointments,groupKey);
// checks if appointment has more than one instances on date
const isMulti = i => counts[groupKey(i)] > 1;
// updated appointment with multiple indicator property
const multiProp = i => ({hasMultipleAppointmentOnDate: isMulti(i) ? "yes": "nope"});
// update initial array items with multiple
const updated = _.map(allAppointments,i => _.extend(i,multiProp(i)));
// see results
console.log(updated);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

underscore.js how to combine 2 collections

I have two collections A and B. ( A,B have the exactly same structure, but different nodes values)
now I'd like to add A into B, with exactly the order: A B and without merging or changing any
nodes inside them. ( just like a joint action) { A } + {B}
I've read the documentation for underscore but couldn't find a proper function which gets this job done.
any idea?
==========update with example ========Sample is simplified from a larger structure, if there are errors please let me know=========
var collection1 = [{
"date": "29 January 2014",
"items": [{
"name": "Jack",
"score": 90,
"title": "programmer"
}, {
"name": "TOM",
"score": 52,
"title": "designer"
}]
}, {
"date": "28 January 2014",
"items": [{
"name": "Jim",
"score": 30,
"title": "driver"
}, {
"name": "William",
"score": 52,
"title": "worker"
}]
}]
var collect2 = [{
"date": "26 January 2014",
"items": [{
"name": "Marry",
"score": 92,
"title": "teacher"
}, {
"name": "TOM",
"score": 52,
"title": "designer"
}]
}]
========expected output==============
[{
"date": "29 January 2014",
"items": [{
"name": "Jack",
"score": 90,
"title": "programmer"
}, {
"name": "TOM",
"score": 52,
"title": "designer"
}]
}, {
"date": "28 January 2014",
"items": [{
"name": "Jim",
"score": 30,
"title": "driver"
}, {
"name": "William",
"score": 52,
"title": "worker"
}]
}, {
"date": "26 January 2014",
"items": [{
"name": "Marry",
"score": 92,
"title": "teacher"
}, {
"name": "TOM",
"score": 52,
"title": "designer"
}]
}]
I think what you are looking for is simply Array.concat
var foo = ['a','b','c'];
var bar = ['d','e','f'];
var all = foo.concat(bar); // ['a','b','c','d','e','f'];
Use Underscore#extend as : _.extend(collection1, collection2);
DEMO
col1 = { aa: 'aa', cc: 'cc' }; col2 = { bb: 'bb', dd: 'dd' };
_.extend(col1, col2)
console.log(col1);
# Prints Object {aa: "aa", cc: "cc", bb: "bb", dd: "dd"}

Categories