Related
I want to pass a function an array of keys and an object, and return a new object that only contains the key/value pairs that I specify in the keys array.
So if I had an object like this:
{"name" : "John Smith", "position" : "CEO", "year" : "2019" }
And I passed the array
["name", "year"]
the new object returned would be:
{"name" : "John Smith", "year" : "2019" }
I've been playing around with it, but my code is not working.
function parse(keys, data) {
let obj = JSON.parse(data);
let newObj = {};
keys.array.forEach(element => {
newObj[element] = obj.element;
});
return newObj;
};
You dont need to do parse.Secondly this line keys.array.forEach is wrong. This is because there is no array key inside keys.Also replace obj.element; with data[element]
let data = {
"name": "John Smith",
"position": "CEO",
"year": "2019"
}
let keys = ["name", "year"]
function parse(keys, data) {
let newJson = {};
keys.forEach(element => {
newJson[element] = data[element];
});
return newJson;
};
console.log(parse(keys, data))
One way to achieve this would be through filtering an array of object entries:
const entries = Object.entries({
"name" : "John Smith",
"position" : "CEO",
"year" : "2019"
})
entries contains:
[
[
"name",
"John Smith"
],
[
"position",
"CEO"
],
[
"year",
"2019"
]
]
Filtering out keys:
const filteredEntries = entries.filter(([ key ]) => ["name", "year"].includes(key))
filteredEntries contains:
[
[
"name",
"John Smith"
],
[
"year",
"2019"
]
]
Last step - construct an object:
const filteredObject = Object.fromEntries(filteredEntries)
filteredObject contains:
{
"name": "John Smith",
"year": "2019"
}
Putting it together as a function:
function filterObjectByGivenKeys(object, keys) {
const filteredEntries = Object
.entries(object)
.filter(([ key ]) => keys.includes(key))
return Object.fromEntries(filteredEntries)
}
Or, if we prefer reduce and more terse syntax:
const filterObjectByGivenKeys = (object, keys) =>
Object.entries(object)
.filter(([ key ]) => keys.includes(key))
.reduce((obj, [key, value]) => ({ ...obj, [key]: value }), {})
The correct (e.g., lazy) way to accomplish this would to use lodash, because code you don't write is code you don't have to maintain:
const pick = require('lodash.pick');
const obj = {
name : 'John Smith' ,
position : 'CEO' ,
year : '2019',
};
const desired = [ 'name', 'year' ];
const filtered = pick(obj, desired );
If you want to roll your own, something like this should do the trick:
function filter_obj(obj = {}, keys = [] ) {
if ( !keys || !keys.length ) return obj;
const desired = new Set(keys);
const filtered = {};
for ( [ key, value ] of Object.entries(obj) ) {
if ( !desired.has(key) ) continue;
filtered[key] = value;
}
return filtered;
}
I think your code is close.
Maybe try:
newObj[element] = obj[element];
instead of
newObj[element] = obj.element
That way you will use the variable element instead of trying to look up the key "element" which will return undefined.
To achieve expected result, use below option of using for in to loop object keys
Loop keys by for in
Check key with the filtered keys
Add to new object
var obj = {"name" : "John Smith", "position" : "CEO", "year" : "2019" }
var fil = ["name", "year"]
var result = {}
for(let key in obj){
if(fil.indexOf(key) !==-1){
result[key] = obj[key]
}
}
console.log(result)
Another option is to use the reduce method:
var input = {"name" : "John Smith", "position" : "CEO", "year" : "2019" };
var properties = ["name", "year"];
function getNewObject(json, props) {
// Get all object properties
var availableProperties = Object.keys(json);
// Loop through the requested properties and return the object
return props.reduce((pv, cv) => {
// Check if the property exists on the object
if(availableProperties.includes(cv)){
pv[cv] = json[cv]
}
return pv;
}, {});
}
console.log(getNewObject(input, properties));
I have removed the object parsing you had above since your object isn't stringified... If it was stringified the "" would be wrapping the entire object... in production you can simple add in the parsing if needed.
function parse(keys, data) {
let newObj = {};
for (const dataKey in data){
for (let i = keys.length - 1; i >= 0; i--) {
if (data.hasOwnProperty(keys[i])) {
newObj[keys[i]] = data[keys[i]];
}
}
}
return newObj;
};
you do that using filter and Object entries or you can also use reduce.
const person = {
"name": "John Smith",
"position": "CEO",
"year": "2019",
"job": "front-end"
};
const formatObject = (arr, o) => {
let finalObject = {};
Object.entries(o).filter(([key, value]) => {
if (arr.includes(key)) {
finalObject = {
...finalObject,
[key]: value
}
}
});
return finalObject;
}
console.log(formatObject(["name", "year", "job"], person))
First add this line {"name" : "John Smith", "position" : "CEO", "year" : "2019" } inside single quotation, or you don't need to use JSON.parse:
'{"name" : "John Smith", "position" : "CEO", "year" : "2019" }'
Then you don't need the array, only keys, keys.array.forEach.
And obj[element]:
keys.forEach(element => {
newObj[element] = obj[element];
});
I have an array which looks like this :
var array =
[
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
},
]
}
]
I want to remove duplicate itemP so with a function it will look like this :
var array =
[
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : null
},
]
}
]
When I try I always have errors. It is possible to do this?
Update
I try to do this :
console.log(array.map(pack =>
pack.values.map((item) => {
var test = JSON.stringify(item)
var set = new Set(test)
return Array.from(set).map((item)=> JSON.parse(item))
}
)
))
Unexpected end of JSON input
I also try something will filter but it doesn't work:
console.log(this.package.map(pack => pack.values.filter(
(value, index , array) => array.itemP.indexOf(value) === index
)))
Instead of mapping every key property, I suggest cloning the whole structure and setting the object value as null in the cloned one, avoiding unintentionally mutating the original structure.
function nullifyDupes(array) {
const clone = JSON.parse(JSON.stringify(array));
const seen = {};
clone.forEach(pack => {
pack.values.forEach(items => {
for (const item in items) {
const id = items[item].id;
if (seen[id]) items[item] = null;
else seen[id] = true;
}
});
});
return clone;
}
const originalArray = [{
key : { id : 1 , pack : "pack 1"},
values : [{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}]
}];
const mutatedArray = nullifyDupes(originalArray);
console.log(mutatedArray);
To achieve expected result, use below option of using map
Loop array using map
Use nameArr to check duplicate and assigning null value
Loop values array and check the name in nameArr using indexOf and assign null
var array = [
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}
]
}
]
console.log(array.map(v => {
let nameArr = []
v.values = v.values.map(val => {
if(nameArr.indexOf(val.itemP.name) !== -1){
val.itemP.name = null
}else{
nameArr.push(val.itemP.name)
}
return val
})
return v
}))
You can use map and an object to check if its already exist. Like
var obj = {}
and loop over values
var values = [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}
]
values.map((v) => {
if(!obj[v.itemP.id + '-' + v.itemP.name]) {
obj[v.itemP.id + '-' + v.itemP.name] = true;
return v;
}
return { item : v.item }
})
You can map your array elements to array objects which don't include your duplicates using .map(). For each iteration of .map() you can again use .map() for your inner values array to convert it into an array of objects such that the duplicates are converted to null. Here I have kept a seen object which keeps track of the properties seen and their stringified values. By looping over all the properties in your object (using for...of), you can work out whether or not the key-value pair has been seen before by using the seen object.
The advantage of this approach is that it doesn't just work with one property (ie not just itemP), but it will work with any other duplicating key-value pairs.
See example below:
const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];
const seen = {};
const res = array.map(obj => {
obj.values = obj.values.map(vobj => {
for (let p in vobj) {
vobj[p] = seen[p] === JSON.stringify(vobj[p]) ? null : vobj[p];
seen[p] = seen[p] || JSON.stringify(vobj[p]);
}
return vobj;
});
return obj;
});
console.log(res);
For an approach which just removed itemP from all object in accross your array you can use:
const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];
let itemP = "";
const res = array.map(obj => {
obj.values = obj.values.map(vobj => {
vobj.itemP = itemP ? null : vobj.itemP;
if('itemP' in vobj) {
itemP = itemP || JSON.stringify(vobj.itemP);
}
return vobj;
});
return obj;
});
console.log(res);
I want to add two nested objects in JSON in typescript.
In JSON given below I want to add second JSON's activityLogs item in first JSON's activityLogs.
JSON1:
[{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
}]
JSON2:
[{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},
{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]
}]
Result:
[{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},
{"gpsdate":"01/03/2019","gpstime":"13:43:18"},
{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
}]
How I can do this?
You can use push() with the spread operator or concat and reassign:
var JSON1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},{"gpsdate":"01/03/2019","gpstime":"13:38:18"},{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]}]
var JSON2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]}]
JSON1[0].activityLogs.push(...JSON2[0].activityLogs)
console.log(JSON1)
This assumes that your json arrays contain just the one top-level object. If that's not the case you need to add more details about how the two arrays are synchronized (for example will vehicleno be the same in both?).
As an example, if the vehicleno is a unique identifier in both arrays you could create a lookup of the JSON1 values and the use that to push into the appropriate arrays. This will update JSON1 in place even if it contains multiple vehicles:
var JSON1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},{"gpsdate":"01/03/2019","gpstime":"13:38:18"},{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]}]
var JSON2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]}]
let lookup = JSON1.reduce((lookup, obj) => {
lookup[obj.vehicleno] = obj
return lookup
}, {})
JSON2.forEach(obj => lookup[obj.vehicleno].activityLogs.push(...obj.activityLogs))
console.log(JSON1)
You can use concatination array method.
let json1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},{"gpsdate":"01/03/2019","gpstime":"13:38:18"},{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]}];
let json2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]}]
let result = json1[0].activityLogs.concat(json2[0].activityLogs);
console.log(result);
The simplest way is to concat the activityLogs:
var arr1 = [{
"vehicleno": "SV028",
"devicE_CODE": "8505",
"activityLogs": [{
"gpsdate": "01/03/2019",
"gpstime": "13:40:18"
},
{
"gpsdate": "01/03/2019",
"gpstime": "13:38:18"
},
{
"gpsdate": "01/03/2019",
"gpstime": "13:37:18"
}
]
}];
var arr2 = [{
"vehicleno": "SV028",
"devicE_CODE": "8505",
"activityLogs": [{
"gpsdate": "01/03/2019",
"gpstime": "13:46:18"
},
{
"gpsdate": "01/03/2019",
"gpstime": "13:43:18"
}
]
}];
var arr3 = arr1[0].activityLogs.concat(arr2[0].activityLogs);
console.log(arr3);
.as-console-wrapper {
max-height: 100% !important;
top: auto;
}
Note this will only work if you only have one object in the top-level array.
result = json1;
/// result = Object.assign({}, json1); if you don't want to mutate the original json1
result.forEach(elem1 => elem1.activityLogs
.concat(json2.find(elem2 => elem2.vehicleno === elem1.vehicleno).activityLogs));
Concat the activityLogs of the second array item to the first array item by finding the matching element by vehicleno..
var json1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
},{"vehicleno":"SV02","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
}]
var json2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},
{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]
}];
var jsonCont = json1.concat(json2);
var result = Object.values(jsonCont.reduce((acc, o)=>{
if(!acc.hasOwnProperty(o['vehicleno'])) {
acc[o['vehicleno']] = Object.assign({}, o);
} else {
acc[o['vehicleno']]['activityLogs'] = acc[o['vehicleno']]['activityLogs'].concat(o['activityLogs']);
}
return acc;
}, {}));
console.log(result);
i have this array of strings :
let myArray : ["AA","BB" , "CC" ...]
I want to convert it to an array of objects:
myArray = [{"id":1 , "value": "AAA"},{"id":2 , "value": "BBB"},{"id":3 , "value": "CCC"}...]
I ve trie with "let for":
for (let obj of ListObj) {
let resObj = {};
resObj ['value'] = obj ;
equipment = resObj ;
}
And with map :
ListObj.map(obj => { 'value' = obj })
Suggestions ?
You can use .map() for this. It passes the index into the callback.
myArray = myArray.map((str, index) => ({ value: str, id: index + 1 }));
I have two arrays. One fetched from an API the other fetched from firebase. They both have a similar key inside of them, that being the tld. As seen below.
API Array
[
{
"tld" : "com",
"tld_type": 1,
},
"tld" : "org",
"tld_type" : 1,
}
]
Firebase Array
[
{
"TLD" : "com",
"register_price" : 14.99
},
{
"TLD" : "org",
"register_price" : 15.99
}
]
I want to combine these two arrays into one and return it like below
[
{
"tld" : "com",
"tld_type" : 1,
"register_price" : 14.99
},
{
"tld" : "org",
"tld_type" : 1,
"register_price" : 15.99
}
]
I've done some google searching and found concact but that doesn't seem to be using the key to find the match. How would I do this?
You can use map and create a new object whose keys and values will be from the other two arrays and return that object. map will create a new array of objects
let api = [{
"tld": "com",
"tld_type": 1,
},
{
"tld": "org",
"tld_type": 1,
}
]
let fb = [{
"TLD": "com",
"register_price": 14.99
},
{
"TLD": "org",
"register_price": 15.99
}
]
let k = api.map(function(item, index) {
let obj = {};
obj.tld = item.tld;
obj['tld_type'] = item['tld_type'];
obj['register_price'] = fb[index]['register_price']
return obj;
});
console.log(k)
There is no unique method for solving that kind of issue. You'll have to loop through all elements and add register_price property if that property exists in firebase array. In shortest possible:
let combined = apiArray.map(ele=>{
let machedElement = fbArray.find(e => e.TLD === ele.tld)
if(machedElement != undefined) ele.register_price = machedElement.register_price
return ele
})
In case if you want to merge all properties not only register_price:
let combined = apiArray.map(ele=>{
let machedElement = fbArray.find(e => e.TLD === ele.tld)
if(machedElement != undefined) {
let mergedObject = Object.assign(ele, machedElement)
return mergedObject
}else{
return ele
}
})