How to separate the difference from an array object? - javascript

My existing array object are
//existing object
var existing = [
{
'ProviderCode':'aa',
'msg':'....',
},{
'ProviderCode':'bb',
'msg':'....',
},{
'ProviderCode':'cc',
'msg':'....',
},{
'ProviderCode':'dd',
'msg':'....',
},{
'ProviderCode':'ee',
'msg':'....',
}];
new object I'm comparing to
var new = [
{
'ProviderCode':'bb',
'msg':'....',
},{
'ProviderCode':'cc',
'msg':'....',
},{
'ProviderCode':'ee',
'msg':'....',
},{
'ProviderCode':'ff',
'msg':'....',
},{
'ProviderCode':'gg',
'msg':'....',
}];
I would like to generate same, remove and add array based on the two array objects, I can get the same array object but not the remove and add object from the objects.
var same = []; //bb, cc, ee //these will be the match
var remove = []; //aa , dd //will be remove from existing
var add = []; //ff, gg //will be consider as add
//I can get the same using below:
e.forEach(function(ev,ei,ea){
n.forEach(function(nv,ni,na){
if( ev.ProviderCode === nv.ProviderCode ){
s.push({ProviderCode:ev.ProviderCode,msg:"Same, do nothing"});
}
});
});
/* //output:
[{
"ProviderCode": "bb",
"msg": "Same, do nothing"
}, {
"ProviderCode": "cc",
"msg": "Same, do nothing"
}, {
"ProviderCode": "ee",
"msg": "Same, do nothing"
}]
*/
//but how do I get remove and add array object?
//remove will be:
/* //output:
[{
"ProviderCode": "aa",
"msg": "removed"
}, {
"ProviderCode": "dd",
"msg": "removed"
}]
*/
//add will be:
/* //output:
[{
"ProviderCode": "ff",
"msg": "added"
}, {
"ProviderCode": "gg",
"msg": "added"
}]
*/

You can use Array.prototype.filter & Array.prototype.find for this:
let existing = [{ProviderCode:'aa'},{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'dd'},{ProviderCode:'ee'}];
let newData = [{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'ee'},{ProviderCode:'ff'},{ProviderCode:'gg'}];
let added = newData.filter(d => !existing.find(e => d.ProviderCode === e.ProviderCode));
console.log("ADDED:", added);
let removed = existing.filter(d => !newData.find(e => d.ProviderCode === e.ProviderCode));
console.log("REMOVED:", added);
let same = newData.filter(d => existing.find(e => d.ProviderCode === e.ProviderCode));
console.log("SAME:", same);
With a library like lodash this is a bit easier:
let existing = [{ProviderCode:'aa'},{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'dd'},{ProviderCode:'ee'}];
let newData = [{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'ee'},{ProviderCode:'ff'},{ProviderCode:'gg'}];
console.log("ADDED:" , _.differenceBy(newData, existing, 'ProviderCode'));
console.log("REMOVED:", _.differenceBy(existing, newData, 'ProviderCode'));
console.log("SAME:" , _.intersectionBy(newData, existing, 'ProviderCode'));
<script src="https://unpkg.com/lodash#4.17.15/lodash.min.js"></script>

You can use this little "library" that provides set operations for JS Map objects:
function mapUnion(m1, m2) {
let m = new Map();
for (let [k, v] of m1)
m.set(k, v);
for (let [k, v] of m2)
m.set(k, v);
return m;
}
function mapIntersection(m1, m2) {
let m = new Map();
for (let [k, v] of m1)
if (m2.has(k))
m.set(k, v);
return m;
}
function mapDifference(m1, m2) {
let m = new Map();
for (let [k, v] of m1)
if (!m2.has(k))
m.set(k, v);
return m;
}
Having this, you can convert both your arrays to Maps:
let m1 = new Map(oldArray.map(x => [x.ProviderCode, x]))
let m2 = new Map(newArray.map(x => [x.ProviderCode, x]))
and do whatever you want with these, for example,
console.log(mapIntersection(m1, m2)) // bb=>..., cc=>..., ee=>...
console.log(mapDifference(m1, m2)) // aa=>..., dd=>...
If you need arrays as results:
commonObjects = Array.from(mapIntersection(m1, m2).values())

You could take some sets and get the wanted items for each change.
const
providerCode = ({ ProviderCode }) => ProviderCode;
var existingData = [{ ProviderCode: 'aa' }, { ProviderCode: 'bb' }, { ProviderCode: 'cc' }, { ProviderCode:'dd' }, { ProviderCode: 'ee' }],
newData = [{ ProviderCode: 'bb' }, { ProviderCode: 'cc' }, { ProviderCode: 'ee' }, { ProviderCode: 'ff' }, { ProviderCode: 'gg' }],
existingSet = new Set(existingData.map(providerCode)),
newSet = new Set(newData.map(providerCode)),
same = [...existingSet].filter(Set.prototype.has, newSet),
add = [...newSet].filter(v => !existingSet.has(v)),
remove = [...existingSet].filter(v => !newSet.has(v));
console.log(...same);
console.log(...add);
console.log(...remove);

Related

Create object from multiple object with same value in map JS [duplicate]

I have an array of objects:
[
{ key : '11', value : '1100', $$hashKey : '00X' },
{ key : '22', value : '2200', $$hashKey : '018' }
];
How do I convert it into the following by JavaScript?
{
"11": "1100",
"22": "2200"
}
Tiny ES6 solution can look like:
var arr = [{key:"11", value:"1100"},{key:"22", value:"2200"}];
var object = arr.reduce(
(obj, item) => Object.assign(obj, { [item.key]: item.value }), {});
console.log(object)
Also, if you use object spread, than it can look like:
var object = arr.reduce((obj, item) => ({...obj, [item.key]: item.value}) ,{});
One more solution that is 99% faster is(tested on jsperf):
var object = arr.reduce((obj, item) => (obj[item.key] = item.value, obj) ,{});
Here we benefit from comma operator, it evaluates all expression before comma and returns a last one(after last comma). So we don't copy obj each time, rather assigning new property to it.
This should do it:
var array = [
{ key: 'k1', value: 'v1' },
{ key: 'k2', value: 'v2' },
{ key: 'k3', value: 'v3' }
];
var mapped = array.map(item => ({ [item.key]: item.value }) );
var newObj = Object.assign({}, ...mapped );
console.log(newObj );
One-liner:
var newObj = Object.assign({}, ...(array.map(item => ({ [item.key]: item.value }) )));
You're probably looking for something like this:
// original
var arr = [
{key : '11', value : '1100', $$hashKey : '00X' },
{key : '22', value : '2200', $$hashKey : '018' }
];
//convert
var result = {};
for (var i = 0; i < arr.length; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result);
I like the functional approach to achieve this task:
var arr = [{ key:"11", value:"1100" }, { key:"22", value:"2200" }];
var result = arr.reduce(function(obj,item){
obj[item.key] = item.value;
return obj;
}, {});
Note: Last {} is the initial obj value for reduce function, if you won't provide the initial value the first arr element will be used (which is probably undesirable).
https://jsfiddle.net/GreQ/2xa078da/
Using Object.fromEntries:
const array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
const obj = Object.fromEntries(array.map(item => [item.key, item.value]));
console.log(obj);
A clean way to do this using modern JavaScript is as follows:
const array = [
{ name: "something", value: "something" },
{ name: "somethingElse", value: "something else" },
];
const newObject = Object.assign({}, ...array.map(item => ({ [item.name]: item.value })));
// >> { something: "something", somethingElse: "something else" }
you can merge array of objects in to one object in one line:
const obj = Object.assign({}, ...array);
Use lodash!
const obj = _.keyBy(arrayOfObjects, 'keyName')
Update: The world kept turning. Use a functional approach instead.
Previous answer
Here you go:
var arr = [{ key: "11", value: "1100" }, { key: "22", value: "2200" }];
var result = {};
for (var i=0, len=arr.length; i < len; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result); // {11: "1000", 22: "2200"}
Simple way using reduce
// Input :
const data = [{key: 'value'}, {otherKey: 'otherValue'}];
data.reduce((prev, curr) => ({...prev, ...curr}) , {});
// Output
{key: 'value', otherKey: 'otherValue'}
More simple Using Object.assign
Object.assign({}, ...array);
Using Underscore.js:
var myArray = [
Object { key="11", value="1100", $$hashKey="00X"},
Object { key="22", value="2200", $$hashKey="018"}
];
var myObj = _.object(_.pluck(myArray, 'key'), _.pluck(myArray, 'value'));
Nearby 2022, I like this approach specially when the array of objects are dynamic which also suggested based on #AdarshMadrecha's test case scenario,
const array = [
{ key : '11', value : '1100', $$hashKey : '00X' },
{ key : '22', value : '2200', $$hashKey : '018' }];
let obj = {};
array.forEach( v => { obj[v.key] = v.value }) //assign to new object
console.log(obj) //{11: '1100', 22: '2200'}
let array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
let arr = {};
arr = array.map((event) => ({ ...arr, [event.key]: event.value }));
console.log(arr);
Was did yesterday
// Convert the task data or array to the object for use in the above form
const {clientData} = taskData.reduce((obj, item) => {
// Use the clientData (You can set your own key name) as the key and the
// entire item as the value
obj['clientData'] = item
return obj
}, {});
Here's how to dynamically accept the above as a string and interpolate it into an object:
var stringObject = '[Object { key="11", value="1100", $$hashKey="00X"}, Object { key="22", value="2200", $$hashKey="018"}]';
function interpolateStringObject(stringObject) {
var jsObj = {};
var processedObj = stringObject.split("[Object { ");
processedObj = processedObj[1].split("},");
$.each(processedObj, function (i, v) {
jsObj[v.split("key=")[1].split(",")[0]] = v.split("value=")[1].split(",")[0].replace(/\"/g,'');
});
return jsObj
}
var t = interpolateStringObject(stringObject); //t is the object you want
http://jsfiddle.net/3QKmX/1/
// original
var arr = [{
key: '11',
value: '1100',
$$hashKey: '00X'
},
{
key: '22',
value: '2200',
$$hashKey: '018'
}
];
// My solution
var obj = {};
for (let i = 0; i < arr.length; i++) {
obj[arr[i].key] = arr[i].value;
}
console.log(obj)
You can use the mapKeys lodash function for that. Just one line of code!
Please refer to this complete code sample (copy paste this into repl.it or similar):
import _ from 'lodash';
// or commonjs:
// const _ = require('lodash');
let a = [{ id: 23, title: 'meat' }, { id: 45, title: 'fish' }, { id: 71, title: 'fruit' }]
let b = _.mapKeys(a, 'id');
console.log(b);
// b:
// { '23': { id: 23, title: 'meat' },
// '45': { id: 45, title: 'fish' },
// '71': { id: 71, title: 'fruit' } }

Map Json data by JavaScript

I have a Json data that I want to have in a different format.
My original json data is:
{
"info": {
"file1": {
"book1": {
"lines": {
"102:0": [
"102:0"
],
"105:4": [
"106:4"
],
"106:4": [
"107:1",
"108:1"
]
}
}
}
}
}
And I want to map it as following:
{
"name": "main",
"children": [
{
"name": "file1",
"children": [
{
"name": "book1",
"group": "1",
"lines": [
"102",
"102"
],
[
"105",
"106"
],
[
"106",
"107",
"108"
]
}
],
"group": 1,
}
],
"group": 0
}
But the number of books and number of files will be more. Here in the lines the 1st part (before the :) inside the "" is taken ("106:4" becomes "106"). The number from the key goes 1st and then the number(s) from the value goes and make a list (["106", "107", "108"]). The group information is new and it depends on parent-child information. 1st parent is group 0 and so on. The first name ("main") is also user defined.
I tried the following code so far:
function build(data) {
return Object.entries(data).reduce((r, [key, value], idx) => {
//const obj = {}
const obj = {
name: 'main',
children: [],
group: 0,
lines: []
}
if (key !== 'reduced control flow') {
obj.name = key;
obj.children = build(value)
if(!(key.includes(":")))
obj.group = idx + 1;
} else {
if (!obj.lines) obj.lines = [];
Object.entries(value).forEach(([k, v]) => {
obj.lines.push([k, ...v].map(e => e.split(':').shift()))
})
}
r.push(obj)
return r;
}, [])
}
const result = build(data);
console.log(result);
The group information is not generating correctly. I am trying to figure out that how to get the correct group information. I would really appreciate if you can help me to figure it out.
You could use reduce method and create recursive function to build the nested structure.
const data = {"info":{"file1":{"book1":{"lines":{"102:0":["102:0"],"105:4":["106:4"],"106:4":["107:1","108:1"]}}}}}
function build(data) {
return Object.entries(data).reduce((r, [key, value]) => {
const obj = {}
if (key !== 'lines') {
obj.name = key;
obj.children = build(value)
} else {
if (!obj.lines) obj.lines = [];
Object.entries(value).forEach(([k, v]) => {
obj.lines.push([k, ...v].map(e => e.split(':').shift()))
})
}
r.push(obj)
return r;
}, [])
}
const result = build(data);
console.log(result);
I couldn't understand the logic behind group property, so you might need to add more info for that, but for the rest, you can try these 2 functions that recursively transform the object into what you are trying to get.
var a = {"info":{"file1":{"book1":{"lines":{"102:0":["102:0"],"105:4":["106:4"],"106:4":["107:1","108:1"]}}}}};
var transform = function (o) {
return Object.keys(o)
.map((k) => {
return {"name": k, "children": (k === "lines" ? parseLines(o[k]) : transform(o[k])) }
}
)
}
var parseLines = function (lines) {
return Object.keys(lines)
.map(v => [v.split(':')[0], ...(lines[v].map(l => l.split(":")[0]))])
}
console.log(JSON.stringify(transform(a)[0], null, 2));

Converting two lists to json

I'm attempting to convert two lists to json.
For example :
l1 = ['a','b','a']
l2 = ['q','r','s']
should be converted to :
[{
"name": "g",
"children": [{
"name": "a",
"children": [{
"name": "q"
}, {
"name": "s"
}]
},
{
"name": "b",
"children": [{
"name": "r"
}]
}
]
}]
Closest I have is :
l1 = ['a','b','a']
l2 = ['q','r','s']
nameDict = {}
childrenDict = {}
l1 = l1.map(x => {
return({name: x});
});
console.log(l1);
l2 = l2.map(x => {
return({children: x});
});
console.log(l2);
var c = l1.map(function(e, i) {
return [e, l2[i]];
});
console.log(JSON.stringify(c))
which produces :
[[{"name":"a"},{"children":"q"}],
[{"name":"b"},{"children":"r"}],
[{"name":"a"},{"children":"s"}]]
How to combine the elements produce ? :
[{
"name": "g",
"children": [{
"name": "a",
"children": [{
"name": "q"
}, {
"name": "s"
}]
},
{
"name": "b",
"children": [{
"name": "r"
}]
}
]
}]
Disclaimer: Since we don't know where the g comes from, I will only build the root children array.
Since your arrays have the same length, you can use a plain for and use with the index to play with both arrays. Just build an array and check each iteration if the "child" already exists. If not, create it.
l1 = ['a','b','a']
l2 = ['q','r','s']
let gChildren = []
for(let i = 0; i < l1.length; i++){
let group = gChildren.find(c => c.name === l1[i])
if(!group){
group = { name: l1[i], children: [] }
gChildren.push(group)
}
group.children.push({ name: l2[i] })
}
console.log(gChildren)
Here is working code that accounts for your pre-existing structure that accomplishes the result you are looking for.
let data1 = ["a","b","a"];
let data2 = ["q","r","s"];
let outputData = [{name: "g", children: []}];
for (let i=0;i < data1.length;i++) {
let found = false;
for (let j=0;j < outputData[0].children.length;j++) {
if (outputData[0].children[j].name === data1[i]) {
outputData[0].children[j].children.push({name: data2[i]});
found = true;
}
}
if (found === false) {
outputData[0].children.push({name: data1[i], children: [{name: data2[i]}]});
}
}
console.log(JSON.stringify(outputData));
This is a good use case for a Array.prototype.reduce, where you want to iterate over an array but end up with a single value.
l1.reduce((acc, val, i) => {
const l2Val = l2[i]
const foundObj = acc.find(o => o.name === val)
if (foundObj) {
foundObj.children.push({name: l2Val})
} else {
acc.push({
name: val,
children: [{name: l2Val}]
})
}
return acc
}, [])
Here, on each iteration I'm just adding the child to the children array for that item, or creating the value for the item if it doesn't already exist.
I have no idea what g corresponds to so I've left it out, but you can add the array created from reduce to another object or array if you want.
You could transpose the array and use the information as path to the final child object
l1 = ['a', 'b', 'a']
l2 = ['q', 'r', 's']
transposes to
[
['a', 'q'], // a -> q
['b', 'r'], // b -> r
['a', 's'] // a -> s
]
which is now works with reduce.
The advantage is to use it with longer pathes to the final children, like
[
['a', 'x', 'y', 'z'],
...
]
which returns a nested object with the given relation to each other.
const
transpose = array => array.reduce((r, a) => a.map((v, i) => [...(r[i] || []), v]), []);
var l1 = ['a', 'b', 'a'],
l2 = ['q', 'r', 's'],
result = transpose([l1, l2]).reduce((r, a) => {
a.reduce((q, name) => {
var temp = (q.children = q.children || []).find(o => o.name === name);
if (!temp) q.children.push(temp = { name });
return temp
}, r);
return r;
}, { name: 'g' });
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A bit shorter with filter on the distinct keys :
var l1 = ['a','b','a'], l2 = ['q','r','s']
var children = [...new Set(l1)].map(k => ({ name: k, children:
l2.filter((v, i) => l1[i] == k).map(v => ({ name: v })) }))
console.log( [{ name: 'g', children }] )
Or more efficient with intermediate object of the groups :
var l1 = ['a','b','a'], l2 = ['q','r','s']
var children = Object.entries(
l1.reduce((o, k, i) => ((o[k] = o[k] || []).push(l2[i]), o), {})
).map(([k, v]) => ({ name: k, children: v.map(v => ({ name: v})) }))
console.log( [{ name: 'g', children }] )

Merge items from two arrays based on matching ID

I have a data object like this :
{
"data1": [
[
"ID",
"name",
"Birthday"
],
[
"10",
"thomas",
"1992-03-17"
],
[
"11",
"Emily",
"2000-03-03"
]
],
"data2": [
[
"Balance",
"ID"
],
[
"$4500",
"10"
],
[
"$1500",
"13"
]
]
}
It contains two arrays data1 and data2.
The first row in each array is the name of the columns and the rest of the rows have the data (think of it like a table).
I want to compare the ID field in both arrays and if the IDs match then the final output will contain a column Balance with the balance corresponding to that ID and if the IDs don't match then the Balance will be $0.
Expected output:
{
"output": [
[
"ID",
"name",
"Birthday",
"Balance"
],
[
"10",
"thomas",
"1992-03-17",
"$4500" //ID 10 matched so the balance added here
],
[
"11",
"Emily",
"2000-03-03",
"0" //0 bcoz the ID 11 is not there in data2 array
]
]
}
I find this challenging to accomplish. Think of it like a LEFT-JOIN in MySQL.
I referred to this solution but it doesn't work in my case as I don't have the keys in my response.
EDIT: I also need to join the other fields as well.
You can use Array.prototype.map(), find, filter, slice, reduce, concat, includes and Object.assign().
This solution:
Handles arbitrary ordering of the items. The order is read from the headers.
Appends a Balance field only if there is one present in data2.
Joins all other fields (requested by OP, see comments below).
Takes default values as an input and uses them if the data is not present in data1 and data2.
function merge({ data1, data2 }, defaults) {
// get the final headers, add/move 'Balance' to the end
const headers = [...data1[0].filter(x => x !== 'Balance')]
.concat(data2[0].includes('Balance') ? ['Balance'] : []);
// map the data from data1 to an array of objects, each key is the header name, also merge the default values.
const d1 = data1.slice(1)
.map(x => x.reduce((acc, y, i) => ({ ...defaults, ...acc, [data1[0][i]]: y }), {}));
// map the data from data2 to an array of objects, each key is the header name
const d2 = data2.slice(1)
.map(x => x.reduce((acc, y, i) => ({ ...acc, [data2[0][i]]: y }), {}));
// combine d1 and d2
const output = d1.map((x, i) => { // iterate over d1
// merge values from d2 into this value
const d = Object.assign(x, d2.find(y => y['ID'] === x['ID']));
// return an array ordered according to the header
return headers.map(h => d[h]);
});
return { output: [headers, ...output] };
}
const test0 = {
data1: [[ "ID","name","Birthday","other"],["10","thomas","1992-03-17","empty"],["11","Emily","2000-03-03","empty"]],
data2: [["other", "ID", "Balance", "city"],["hello", "10", "$4500", "New York"],["world", "10","$8","Brazil"]]
};
const test1 = {
data1: [["ID","name","Birthday"],["10","thomas","1992-03-17"],["11","Emily","2000-03-03"]],
data2: [["other","ID"],["x","10"],["y","11"]]
};
console.log(merge(test0, { Balance: '$0' }));
console.log(merge(test1, { Balance: '$0' }));
const KEY_ID = "ID";
var data = {
"data1": [
[ "ID", "name", "Birthday" ],
[ "10", "thomas", "1992-03-17" ],
[ "11", "Emily", "2000-03-03" ]
],
"data2": [
[ "Balance", "ID" ],
[ "$4500", "10" ],
[ "$1500", "13" ]
]
}
var merged = Object.keys(data).map(function (key) {
var tmp = data[key].slice();
var heads = tmp.shift();
return tmp.map(function (item) {
var row = {};
heads.forEach(function (head, i) {
row[head] = item[i];
});
return row;
});
}).flat().reduce(function (acc, row) {
var found = acc.find(function (item) {
return row[KEY_ID] === item[KEY_ID];
})
if (!found) {
found = row;
acc.push(found);
} else {
Object.keys(row).forEach(function (head) {
found[head] = row[head];
});
}
return acc;
}, []);
console.log(merged);
This solution is scalable: if you add properties, it will scale the new format.
let a = { "data1": [ ... ],"data2": [ ...] }
let r = a.data1.reduce((r,u,i)=>{
if(i !== 0)
{
let entry = a.data2.filter((a)=> a[1]===u[0])
r.push([...u,entry.length ? entry[0][0] : 0])
}
return r
},[[
"ID",
"name",
"Birthday",
"Balance"
]])
You could abstract all table operations into a class-like:
function Table(array) {
const [head, ...values] = array;
const Entry =(entry) => ({
get(key) { return entry[ head.indexOf(key) ]; },
set(key, value) { entry[ head.indexOf(key) ] = value; }
});
return {
index(name) {
const result = {};
for(const value of values)
result[ value[ head.indexOf(name) ] ] = Entry(value);
return result;
},
*[Symbol.iterator]() {
for(const row of values)
yield Entry(row);
},
addRow(key) { head.push(key); }
};
}
Usable as:
const users = Table(obj.data1);
const balances = Table(obj.data2);
const balanceByID = balance.index("ID");
users.addRow("Balance");
for(const user of users)
user.set("Balance", balanceByID[ user.get("ID") ].get("Balance"));

How to create a single object from key-value pairs objects in JavaScript?

I have several objects and I want to create another one that will have keys from a particular array (const props = []), and values from those objects - if it only exists in those objects, but if not - I want to push null or some other fake values.
My code:
const props = ["name", "price", "qty", "category"]
let len = props.length;
const obj_1 = {
name: "Product_1",
price: 120,
category: 'phone'
}
const obj_2 = {
name: "Product_2",
price: 7893,
category: 'program_eq',
qty: 5
}
const final_obj = {
name: ["Product_1", "Product_2"],
price: [120, 7893],
category: ["phone", "program_eq"],
qty: [null, 5]
}
I have spent lots of time with this problem and have some solution - but it gives me only the first object.
I am using lodash/map and it helps me to work with different type of collection.
You can see my solution bellow:
const final_obj = {};
const props = ["name", "price", "qty", "category"];
let len = props.length;
const obj = {
c1s6c156a1cascascas: {
item: {
name: "Product_1",
price: 120,
category: "phone"
}
},
c454asc5515as41cas78: {
item: {
name: "Product_2",
price: 7893,
category: "program_eq",
qty: 5
}
}
};
_.map(obj, (element, key) => {
console.log(element.item);
while (len) {
let temp = props.shift();
let tempData = [];
if (element.item.hasOwnProperty([temp])) {
tempData.push(element.item[temp]);
} else {
tempData.push("---");
}
final_obj[temp] = tempData;
len--;
}
});
console.log(final_obj);
//
category:["phone"]
name:["Product_1"],
price:[120],
qty:["---"],
You could do this with reduce() method that will return object and inside use forEach() loop.
const props = ["name", "price", "qty", "category"];
const obj = {"c1s6c156a1cascascas":{"item":{"name":"Product_1","price":120,"category":"phone"}},"c454asc5515as41cas78":{"item":{"name":"Product_2","price":7893,"category":"program_eq","qty":5}}}
const result = Object.values(obj).reduce((r, e) => {
props.forEach(prop => {
if(!r[prop]) r[prop] = []
r[prop].push(e.item[prop] || null)
})
return r;
}, {})
console.log(result)
This is how I would handle it:
const final_obj = { };
const props = ["name", "price", "qty", "category"];
const obj = {"c1s6c156a1cascascas":{"item":{"name":"Product_1","price":120,"category":"phone"}},"c454asc5515as41cas78":{"item":{"name":"Product_2","price":7893,"category":"program_eq","qty":5}}}
// set up each property as an empty array in the object
props.forEach(item => {
final_obj[item] = [];
});
// this iterates over every property in the object
_.forOwn(obj, value => {
props.forEach(item => {
// just push the values undefined or no into each property array
final_obj[item].push(value.item[item]);
});
});
console.log(final_obj);
You can do as well using some lodash functions.
Transform the array of props into an object which keys are the values of props and which values are extracted from the object. If the property doesn't exist in the object, return null.
const getValFromObj = (obj, key) => _.map(obj, _.partial(_.get, _, key, null));
const setValInResult = (res, key) => _.set(res, key, getValFromObj(obj, 'item.' + key));
const groupByProps = (props, obj) => _.transform(props, setValInResult, {});
const props = ["name", "price", "qty", "category"];
const obj = {
"c1s6c156a1cascascas": {
"item": {
"name": "Product_1",
"price": 120,
"category": "phone"
}
},
"c454asc5515as41cas78": {
"item": {
"name": "Product_2",
"price": 7893,
"category": "program_eq",
"qty": 5
}
}
}
console.log(groupByProps(props, obj));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>

Categories