Best way to map this object into a new object - javascript

Using lodash or vanilla javascript, I need to convert this json:
{
"results" : [
{
"values" : [
{"label" : "FOO", "value" : "foovalue" },
{"label" : "BAR", "value" : "barvalue1" },
{"label" : "BAR", "value" : "barvalue2" }
]
},
{
"values" : [
{"label" : "FOO", "value" : "foovalue"},
{"label" : "BAR", "value" : "barvalue1"},
{"label" : "BAR", "value" : "barvalue2"}
]
}
]
}
into a new object where the label values become the key and duplicates are made into an array of new objects like this:
[
[{"FOO" : "foovalue", "BAR" : ["barvalue1", "barvalue2"]}],
[{"FOO" : "foovalue", "BAR" : ["barvalue1", "barvalue2"]}]
]
I've tried using _.map but it is overwriting the duplicate values and I need them all in an array.
Here is the closest I've come:
var arr = _.map(results, function(o) {
return _.map(o.values, function(v) {
var obj = {};
obj[t.label] = t.value;
return obj;
});
});
where arr returns an array of the objects like this (with the objects being overwritten and not combined into a single object) [{"FOO" : "foovalue"},{"BAR" : "barvalue2"}] and I'm stuck trying to make them into the above array.

You could map the outer array and reduce the inner array by collecting the values of labels. If more than one collected element use an array.
var results = [{ values: [{ label: "FOO", value: "foovalue" }, { label: "BAR", value: "barvalue1" }, { label: "BAR", value: "barvalue2" }] }, { values: [{ label: "FOO", value: "foovalue" }, { label: "BAR", value: "barvalue1" }, { label: "BAR", value: "barvalue2" }] }],
grouped = results.map(({ values }) => [
values.reduce((o, { label, value }) => {
if (!o[label]) {
o[label] = value;
return o;
}
if (!Array.isArray(o[label])) {
o[label] = [o[label]];
}
o[label].push(value);
return o;
}, {})
]);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Methods to insert or replace values in to object

I've got an object like this
var obj2= {
'home' : {
'1' : {
'year' : '1999'
},
'2' : {
'year' : '2000'
'month' : '11'
},
},
'company' : {
'1' : {
'year' : '2010'
'month' : '2'
},
}
};
And I would like to add some more keys inside the object or replace value if this key chain already exists, for ex:
buss_type = "home",
type_id = "1",
date_type = "month",
value = "9"
var tmp_obj1 = {[buss_type]: {[type_id]: {[date_type]: value}}};
and
buss_type = "company",
type_id = "2",
date_type = "month",
value = "12"
var tmp_obj2 = {[buss_type]: {[type_id]: {[date_type]: value}}};
to make object:
obj = {
'home' : {
'1' : {
'year' : '1999',
'month' : '9'
},
'2' : {
'year' : '2000',
'month' : '11'
},
},
'company' : {
'1' : {
'year' : '2020',
'month' : '10'
},
'2' : {
'month' : '12'
}
},
};
Arrays methods like .push() or .concat() adding new keys on the end only instead of replacing values of existing ones.
Are there any object methods that can make it easy to manage or should I just use loops and check all keys before adding new or changing value of existing one?
Thanks.
You could take an array for the keys and save the last key for direct assignment.
function setValue(object, path, value) {
var last = path.pop();
path.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var object = { home: { 1: { year: '1999' }, 2: { year: '2000', month: '11' } }, company: { 1: { year: '2010', month: '2' } } };
setValue(object, ["home", "1", "month"], "9");
setValue(object, ["company", "2", "month"], "12");
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use reduce() method to add nested properties to object.
var obj2 = {"home":{"1":{"year":"1999"},"2":{"year":"2000","month":"11"}},"company":{"1":{"year":"2010","month":"2"}}}
function add(obj, value, ...keys) {
keys.reduce(function(r, e, i, arr) {
return r[e] || (r[e] = arr[i + 1] ? {} : value)
}, obj)
}
let buss_type = "home", type_id = "1", date_type = "month", value = "9";
add(obj2, value, buss_type, type_id, date_type)
buss_type = "company", type_id = "2", date_type = "month", value = "12"
add(obj2, value, buss_type, type_id, date_type)
console.log(obj2)
If you will only have objects without any methods inside, just simple JSON style objects. Then you can use something like
JSON.stringify(obj1) === JSON.stringify(obj2)
Just be careful that the order of the object data is important. For example, this will return false
x = {a: 1, b: 2};
y = {b: 2, a: 1};
You don't need to create a loop instead you can programmatically access the key you're about to add using this syntax:
buss_type = "home",
type_id = "1",
date_type = "month",
value = "9"
if(obj[buss_type]){
if(obj[buss_type][type_id]){
obj[buss_type][type_id][date_type] = value
}else{
obj[buss_type][type_id] = { date_type: value }
}
}else{
obj[buss_type] = { type_id: { date_type: value } }
}

Convert Flat JSON Array to JSON Object in Nodejs

I have a flat json array that store data like this:
[
{
"prop1": "prop1Data1"
},
{
"prop2": "prop2Data1"
},
{
"prop3.name": "Tom"
}
]
How can I convert this data into simple json object in node js like this:
{ "prop1": "prop1Data1", "prop2": "prop2Data1", "prop3.name": "Tom" }
You could use Object.assign and use spread syntax ... for the array.
var array = [{ prop1: "prop1Data1" }, { prop2: "prop2Data1" }, { "prop3.name": "Tom" }],
object = Object.assign({}, ...array);
console.log(object);
ES5 with Array#reduce and by iterating the keys.
var array = [{ prop1: "prop1Data1" }, { prop2: "prop2Data1" }, { "prop3.name": "Tom" }],
object = array.reduce(function (r, o) {
Object.keys(o).forEach(function (k) {
r[k] = o[k];
});
return r;
}, {});
console.log(object);
The way that I've done it was like so, since it is within an array.
var original = [{"prop1": "prop1Data1"},{"prop2": "prop2Data1"},{"prop3.name": "Tom"}];
var propStore = {
prop1 : '',
prop2 : '',
prop3 : ''
}
propStore.prop1 = original[0]["prop1"];
propStore.prop2 = original[0]["prop2"];
propStore.prop3 = original[0]["prop3"];
console.log(propStore);

Javascript : Determine duplicate objects in an array and return array of them

I have an array of objects
[
{
classname: ".icon"
data : "12"
},
{
classname: ".icon1"
data : "34"
},
{
classname: ".icon2"
data : "56"
},
{
classname: ".icon"
data : "78"
},
{
classname: ".icon1"
data : "90"
},
{
classname: ".icon1"
data : "AB"
}
]
I want to return an array of array grouped by their duplication, like this
[
{
classname: ".icon"
data : "12"
},
{
classname: ".icon"
data : "78"
}
]
[
{
classname: ".icon1"
data : "34"
},
{
classname: ".icon1"
data : "90"
},
{
classname: ".icon1"
data : "AB"
}
]
I can use lodash as well as native JavaScript.
Important: The order of their original occurrence must be maintained in the returned array of array.
I am keying on the property name 'classname'
You can do this with reduce()
var data = [{"classname":".icon","data":"12"},{"classname":".icon1","data":"34"},{"classname":".icon2","data":"56"},{"classname":".icon","data":"78"},{"classname":".icon1","data":"90"},{"classname":".icon1","data":"AB"}]
var obj = {}
var result = data.reduce(function(r, e) {
if (!obj[e.classname]) {
obj[e.classname] = []
r.push(obj[e.classname])
}
obj[e.classname].push(e)
return r;
}, [])
console.log(result)

Refactoring object into a flat array

I have an object like this.
{Brunch: 2, Kimchi: 1}
I need to refactor it into an an array/object
[{
"label" : "Brunch",
"value" : 2
},
{
"label" : "Kimchi",
"value" : 1
}]
You can use Object.keys() and map() to get desired result.
var obj = {
Brunch: 2,
Kimchi: 1
}
var result = Object.keys(obj).map(function(k) {
return {
"label": k,
"value": obj[k]
}
})
console.log(result)
The simplest way:
var result = Object.keys(input).map(key => ({
label: key,
value: input[key],
}));

Sorting array into array new based on string

I'm trying to sort a JSON into multiple arrays based on type, my current json is:
// current json file:
{
"res": [
{
"type" : "stream",
"price" : "3.99",
"id" : "13nee"
},
{
"type" : "stream",
"price" : "2.99",
"id" : "8ejwj"
},
{
"type" : "buy",
"price" : "3.99".
"id" : "9akwk"
},
...
]
}
I'm looking to sort it into multiple arrays by type like below:
var sorted = {
"stream" : [
{
"price" : "2.99",
"id" : "8ejwj"
},
{
"price" : ".99",
"id" : "13nee"
},
... // other objects with type: "stream"
],
"buy" : [
{
"price" : "3.99".
"id" : "9akwk"
},
... // other objects with type: "buy"
]
}
I've tried it, but the only solution I can think of is by cases - run if loop, if case matches type, then push object to array. Is there a more elegant solution?
var items = {};
var i = 0;
for(i; i < res.length; i += 1){
var resItem = res[i];
if(items.hasOwnProperty(resItem.type)){
items[resItem.type].push({price:resItem.price, id:resItem.id});
} else {
items[resItem.type] = [{price:resItem.price, id:resItem.id}];
}
}
The properties on JavaScript objects are hashed, so you can dynamically match and generate new objects like above. If you want to apply a well ordering sort, you'll need to apply it to the arrays of the newly generated items object.
Step 1 :
Convert the JSON to a jquery object :
var x = jQuery.parseJSON( jsonString );
Step 2:
Use underscore library's _.groupBy to group :
_.groupBy(x,'type');
There might be some adjustment you need to do for x being array or object.
Edit :
You don't need step1. Just do :
sorted = _.groupBy(json.res,'type');
You could do something like this with ECMA5. This performs, generically, the sort and reduce that you have indicated in your question, so you can add more fields to your data without having to change the routine. It also leaves your original data intact.
Javascript
var original = {
'res': [{
'type': 'stream',
'price': '3.99',
'id': '13nee'
}, {
'type': 'stream',
'price': '2.99',
'id': '8ejwj'
}, {
'type': 'buy',
'price': '3.99',
'id': '9akwk'
}]
},
sorted = {};
original.res.slice().sort(function (a, b) {
a = +(a.price);
b = +(b.price);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}).reduce(function (acc, element) {
if (!acc[element.type]) {
acc[element.type] = [];
}
acc[element.type].push(Object.keys(element).filter(function (name) {
return name !== 'type';
}).reduce(function (prev, name) {
prev[name] = element[name];
return prev;
}, {}));
return acc;
}, sorted);
console.log(JSON.stringify(sorted));
Output
{
"stream": [{
"price": "2.99",
"id": "8ejwj"
}, {
"price": "3.99",
"id": "13nee"
}],
"buy": [{
"price": "3.99",
"id": "9akwk"
}]
}
On jsFiddle

Categories

Resources