Get parent array key in deep nested object using lodash - javascript

I'm using Lodash JavaScript library in my project and have a problem in getting the parent array key object filtered object:
I've the following data:
var data = {
5: [{
id: "3",
label: "Manish"
}, {
id: "6",
label: "Rahul"
}, {
id: "7",
label: "Vikash"
}],
8: [{
id: "16",
label: "Pankaj"
}, {
id: "45",
label: "Akash"
}],
9: [{
id: "15",
label: "Sunil"
}]
}
My requirement is if I've the array of [6,16] then I want a new result array containing values 5,8 because these two array keys have objects which contain id:"6" and id:"16"
I tried it using _.flatten and _.pick method but could not work. I used the following code;
var list = [];
_.each(data, function(item){
list.push(_.omit(item, 'id'));
list.push(_.flatten(_.pick(item, 'id')));
});
var result = _.flatten(list);
console.log(result);

var res = _([6, 16]).map(function(id){
return _.findKey(data, function(arr){
return _.some(arr, {id: new String(id)});
})
}).compact().uniq().value();

If simple javascript solution is okay with you then
var searchId=[6,16];
var newArr = [];
for ( key in data ){
data[key].forEach( function(innerValue){
if ( searchId.indexOf( Number(innerValue.id) ) != -1 ) newArr.push( key );
} );
}
console.log(newArr);

try this:
( hope im not missing some syntax )
var result = [];
var filterArray = [6,16];
_.each(filterArray, function(item){
_.merge(result,_.filter(data, function(o) { return _.contains(o,{id:item}) }));
});

Using _.pickBy this problem is solved simply:
var myArr = [6, 16]
var res = _.pickBy(data, function (value) {
return _(value).map('id').map(_.toNumber).intersection(myArr).size();
});
console.log(res)
https://jsfiddle.net/7s4s7h3w/

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' } }

formatting dynamic json array

I have an json array as follows:
Maindata=[
{"name":"string1"},
{"name":"string2"},
{"name":"string3"}
];
what I need is an array of following type:
data=[
{
"name":"string1",
"name":"string2",
"name":"string3"
}
];
can anybody help me with some methods to obtain required json from original array.
(note: maindata is json array formed dynamically thats why its structure is like that)
Thanks in advance
You could use Object.assign and spread the array elements.
var array = [{ name1: "string1" }, { name2: "string2" }, { name3: "string3" }],
object = Object.assign({}, ...array);
console.log(object);
With reduce, you can do like following
var Maindata = [{
"name1": "string"
}, {
"name2": "string"
}, {
"name3": "string"
}];
var finalObj = Maindata.reduce((acc, cur) => {
Object.assign(acc, cur);
return acc;
}, {})
console.log(finalObj);
You can use Array.forEach or Array.reduce to iterate though the items of the Maindata object and for each item you can iterate through its keys(using Object.keys) and group the data into a new structure.(See the below snippet)
Solution using Array.forEach
var Maindata=[
{"name1":"string1"},
{"name2":"string2"},
{"name3":"string3"}
];
var result = {};
var newMaindata=[];
Maindata.forEach(function(el){
Object.keys(el).forEach(function(key){
result[key]=el[key];
});
});
newMaindata.push(result);
console.log(newMaindata);
Solution using Array.reduce
var Maindata = [{
"name1": "string1"
}, {
"name2": "string2"
}, {
"name3": "string3"
}];
var result ;
var newMaindata = [];
result = Maindata.reduce(function(acc,el) {
Object.keys(el).forEach(function(key) {
acc[key] = el[key];
});
return acc;
},{});
newMaindata.push(result);
console.log(newMaindata);

convert array into an array of ojects

I have the following array list.
var data = [ "USA", "Denmark", "London"];
I need to convert it in this form
var data = [
{ "id" : 1, "label": "USA" },
{ "id" : 2, "label": "Denmark" },
{ "id" : 3, "label": "London" }
];
Can anyone please let me know how to achieve this.
Pretty easy using Array.map (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
var formatted = data.map(function(country, index) {
return { id: (index + 1), label: country }
});
Simple version:
var convertedData = []
for (var i in data){
convertedData.push({id: i+1, label: data[i]});
}
data = convertedData; //if you want to overwrite data variable
You can use forEach to loop through the data array
var data = [ "USA", "Denmark", "London"];
var demArray =[];
data.forEach(function(item,index){
demArray.push({
id:index+1,
label:item
})
})
console.log(demArray)
JSFIDDLE
Underscore way (for old browsers without Array.map support):
var res = _.map(data, function(p, i){
return {id: i + 1, label: p};
});

array map, map array as a key of an array

I know the title might sounds confusing, but i'm stuck for an hour using $.each. Basically I have 2 arrays
[{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
and [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
How do I put one into another as a new property key like
[{
"section_name": "abc",
"id": 1,
"new_property_name": [{
"toy": "car"
}, {
"tool": "knife"
}]
}, {
"section_name": "xyz",
"id": 2,
"new_property_name": [{
"weapon": "cutter"
}]
}]
ES6 Solution :
const arr = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
const arr2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
const res = arr.map((section,index) => {
section.new_property_name = arr2.filter(item => item.id === section.id);
return section;
});
EDIT : Like georg mentionned in the comments, the solution above is actually mutating arr, it modifies the original arr (if you log the arr after mapping it, you will see it has changed, mutated the arr and have the new_property_name). It makes the .map() useless, a simple forEach() is indeed more appropriate and save one line.
arr.forEach(section => {
section.new_property_name = arr2.filter(item => item.id === section.id));
});
try this
var data1 = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var data2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
var map = {};
//first iterate data1 the create a map of all the objects by its ids
data1.forEach( function( obj ){ map[ obj.id ] = obj });
//Iterate data2 and populate the new_property_name of all the ids
data2.forEach( function(obj){
var id = obj.id;
map[ id ].new_property_name = map[ id ].new_property_name || [];
delete obj.id;
map[ id ].new_property_name.push( obj );
});
//just get only the values from the map
var output = Object.keys(map).map(function(key){ return map[ key ] });
console.log(output);
You could use ah hash table for look up and build a new object for inserting into the new_property_name array.
var array1 = [{ "section_name": "abc", "id": 1 }, { "section_name": "xyz", "id": 2 }],
array2 = [{ "toy": "car", "section_id": 1 }, { "tool": "knife", "section_id": 1 }, { "weapons": "cutter", "section_id": 2 }],
hash = Object.create(null);
array1.forEach(function (a) {
a.new_property_name = [];
hash[a.id] = a;
});
array2.forEach(function (a) {
hash[a.section_id].new_property_name.push(Object.keys(a).reduce(function (r, k) {
if (k !== 'section_id') {
r[k] = a[k];
}
return r;
}, {}));
});
console.log(array1);
Seems like by using Jquery $.merge() Function you can achieve what you need. Then we have concat function too which can be used to merge one array with another.
Use Object.assign()
In your case you can do it like Object.assign(array1[0], array2[0]).
It's very good for combining objects, so in your case you just need to combine your objects within the array.
Example of code:
var objA = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var objB = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var objC = Object.assign({},objA[0],objB[0]);
console.log(JSON.stringify(objC));// {"section_name":"abc","id":1,"toy":"car","section_id":1}
For more info, you can refer here: Object.assign()
var firstArray = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}],
secondArray = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var hash = Object.create(null);
firstArray.forEach(s => {
hash[s.id] = s;
s['new_property_name'] = [];
});
secondArray.forEach(i => hash[i['section_id']]['new_property_name'].push(i));
console.log(firstArray);

Remove objects from array of object in javascript

I'm trying to remove objects from an array of object using a delta data i'm getting from server. I'm using underscore in my project.
Is there a straight forward way to do this, rather going with looping and assigning ?
Main Array
var input = [
{name: "AAA", id: 845,status:1},
{name: "BBB", id: 839,status:1},
{name: "CCC", id: 854,status:1}
];
Tobe Removed
var deltadata = [
{name: "AAA", id: 845,status:0},
{name: "BBB", id: 839,status:0}
];
Expected output
var finaldata = [
{name: "CCC", id: 854,status:1}
]
Try this
var finaldata = _.filter(input, function(item) {
return !(_.findWhere(deltadata, {id: item.id}));
});
It does assume that you have unique ID's. Maybe you can come up with something better.
Here's a simple solution. As others have mentioned, I don't think this is possible without a loop. You could also add checks for status and name in the condition, as this just compares IDs.
var finaldata = input.filter(function(o) {
for (var i = 0; i < deltadata.length; i++)
if (deltadata[i].id === o.id) return false;
return true;
});
A simple filter will do it:
var finaldata = _.filter(input, function(o) {
return _.findWhere(deltadata, o) === undefined;
});
A little more efficient than the findWhere would be creating a lookup map with ids to remove, and then filtering by that:
var idsToRemove = _.reduce(deltadata, function(m, o) {
m[o.id] = true;
return m;
}, {});
var finaldata = _.reject(input, function(o) { return o.id in idsToRemove; });

Categories