I have an array with few values. I want to iterate over array and add those values to an object as value starting from second object element which has null value. I cannot figure out how can I do it properly. Here is my code
let objectParameters = {
"current_lang" : currentLang,
"project_name" : null,
"project_type" : null,
"min_price" : null,
"max_price" : null
}
let arrayValues = ["Project name", "Project Type", 150, 950];
arrayValues .forEach(function(item) {
//Add array value to an object
}
Desired output
let objectParameters = {
"current_lang" : currentLang,
"project_name" : "Project name",
"project_type" : "Project Type",
"min_price" : 150,
"max_price" : 950
}
Came up with this :
let objectParameters = {
"current_lang" : "currentLang",
"project_name" : null,
"project_type" : null,
"min_price" : null,
"max_price" : null
};
let arrayValues = ["Project name", "Project Type", 150, 950],
keys = Object.keys(objectParameters);
keys.shift() // Removing the first key, which is not null
keys.forEach( (key,i) => objectParameters[key] = arrayValues[i])
console.log(objectParameters)
You can get all the properties of an object with
Object.keys(objectParameters)
as an array and assign them values from your arrayValues
Like that:
let objectParameters = {
"current_lang" : "en",
"project_name" : null,
"project_type" : null,
"min_price" : null,
"max_price" : null
}
let arrayValues = ["Project name", "Project Type", 150, 950];
let params = Object.keys(objectParameters);
for(let i = 1; i < params.length; i++) {
objectParameters[params[i]] = arrayValues[i-1];
}
console.log(objectParameters);
Using for in loop to iterate through the object and shift() to get the first array element each iteration, in all cases we rely on the order, that is probably not a good approach.
let objectParameters = {
"current_lang" : "currentLang",
"project_name" : null,
"project_type" : null,
"min_price" : null,
"max_price" : null
}
let arrayValues = ["Project name", "Project Type", 150, 950];
for(let p in objectParameters){
if(!objectParameters[p])
objectParameters[p] = arrayValues.shift()
}
console.log(objectParameters)
I don't see necessary to use hasOwnProperty in this case.
If you know the index of the corresponding value in the array you dont need the loop and can just do:
objectParameters["project_name"] = arrayValues[0]
objectParameters["project_type"] = arrayValues[1]
...
if you have the array values when youre creating the object you can just use them at the object creation time:
let objectParameters = {
"current_lang" : "en",
"project_name" : arrayValues[0],
...
}
Well, if you got ordered array and object, here this code might help you:
var obj = {
'first': '1',
'second': '2'
};
var arr = ['first', 'sec'];
Object.keys(obj).forEach(function (key, arrIndex) {
obj[key] = arr[arrIndex];
});
Then you edit and optimize it the way you want.
Little improvement, thank to #Jeremy Thille
If your arrayValues format value will be same then you could use separate keys and use reduce() method for your arrays values and Destructuring_assignment.
DEMO
const keys = ["project_name", "project_type", "min_price", "max_price"],
arrayValues = ["Project name", "Project Type", 150, 950];
let result = arrayValues.reduce((r, v, i) => {
return { ...r,
[keys[i]]: v
}
}, {current_lang:navigator.language});
console.log(result)
.as-console-wrapper {max-height: 100% !important;top: 0;}
Related
i have an object
{
"name" : "foo",
"tag_name" : "grocery",
"tag_id" : "id",
"tag_nested_id" : "123",
}
I want the output as
{
"name" : "foo",
"tag" : {
"name" : "grocery",
"id" : "id",
"nested" : {
"id" : "123"
}
}
}
Is there any easy way to achieve this using lodash/underscore?
No external libraries required, vanilla JS split on _ and .reduce
const data = {
"name" : "foo",
"tag_name" : "grocery",
"tag_id" : "id",
"tag_nested_id" : "123"
};
const result = Object.entries(data).reduce((object, [key, val]) => {
const splitKey = key.split('_');
const last = splitKey.pop();
splitKey.reduce((obj, x) => obj[x] ??= {}, object)[last] = val;
return object;
}, {})
console.log(JSON.stringify(result, null, 2));
The answer by mani is as good as it gets, but with Underscore, we can create a version that is backwards compatible with older environments:
var data = {
"name" : "foo",
"tag_name" : "grocery",
"tag_id" : "id",
"tag_nested_id" : "123"
};
var result = _.reduce(data, function(object, val, key) {
var splitKey = key.split('_');
var last = splitKey.pop();
_.reduce(splitKey, function(obj, part) {
return obj[part] = obj[part] || {};
}, object)[last] = val;
return object;
}, {})
console.log(JSON.stringify(result, null, 2));
<script src="https://cdn.jsdelivr.net/npm/underscore#1.13.4/underscore-umd-min.js"></script>
I have an object from user input. The keys to that object are separated by commas, and I just want to separate those keys and make the keys of the object.
The key_array below is dynamic from user input, generates a different array each time, below I give you an example.
I have shown the object in my code which you can see below. you can also see the output by running that code.
var main_array = {};
var key_array = {
'user,name' : 'user name',
'user,email' : 'Email address',
'order,id' : 123456,
'order,qty' : 2,
'order,total' : 300,
'order,product,0,name' : "product1",
'order,product,0,qty' : 1,
'order,product,0,price' : 100,
'order,product,1,name' : "product2",
'order,product,1,qty' : 1,
'order,product,1,price' : 200,
};
for (keys in key_array){
var value = key_array[keys];
// What do I do here to get the output I want?
main_array['[' + keys.split(",").join('][')+ ']'] = value;
}
console.log(main_array);
Running the code above will give you the following output which is incorrect. And the output I don't want.
{
[order][id]: 123456,
[order][product][0][name]: "product1",
[order][product][0][price]: 100,
[order][product][0][qty]: 1,
[order][product][1][name]: "product2",
[order][product][1][price]: 200,
[order][product][1][qty]: 1,
[order][qty]: 2,
[order][total]: 300,
[user][email]: "Email address",
[user][name]: "user name"
}
I want an output like JSON below, so please tell me how to do it.
{
"user":{
"email" : "Email address",
"name" : "user name"
},
"order":{
"id" : 123456,
"qty" : 2,
"total" : 300,
"product":[
{
"name" : "product1",
"price" : 100,
"qty" : 1
},{
"name" : "product2",
"price" : 200,
"qty" : 1
}
]
}
}
Note: Please do not use eval, as using eval in this way is terribly unreliable, bad work and unsafe. Because I get all my data from user input, the likelihood of abuse can increase.
Use Object.entries to go over key and values of object.
Split the key by , separator and then build the object.
While building object, make sure to merge the keys and values using mergeTo method.
Then convert the objects which has the numerical keys then convert to object using convertObjsToArray method.
var key_array = {
"user,name": "user name",
"user,email": "Email address",
"order,id": 123456,
"order,qty": 2,
"order,total": 300,
"order,product,0,name": "product1",
"order,product,0,qty": 1,
"order,product,0,price": 100,
"order,product,1,name": "product2",
"order,product,1,qty": 1,
"order,product,1,price": 200
};
const mergeTo = (target, obj) => {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === "object" && !Array.isArray(value)) {
if (!target[key]) {
target[key] = {};
}
mergeTo(target[key], obj[key]);
} else {
target[key] = value;
}
});
};
const convertObjsToArray = obj => {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === "object") {
if (Object.keys(value).every(num => Number.isInteger(Number(num)))) {
obj[key] = Object.values(value);
} else {
convertObjsToArray(obj[key]);
}
}
});
};
const res = {};
Object.entries(key_array).map(([key, value]) => {
const keys = key.split(",");
let curr = { [keys.pop()]: value };
while (keys.length > 0) {
curr = { [keys.pop()]: curr };
}
mergeTo(res, curr);
});
convertObjsToArray(res);
console.log(res);
You can create the objects and keys required from the string dynamically, take each key and split it to an array using split(','). Using each item in the array create the structure required. Assuming if a key is a number, then it's parent must be an array.
Object.keys(key_array).forEach(key => {
const path = key.split(',');
let current = main_array;
for (let i = 0; i < path.length - 1; i++) {
if (!current[path[i]]) {
current[path[i]] = path[i + 1] && !isNaN(path[i + 1]) ? [] : {};
}
current = current[path[i]];
}
current[path.pop()] = key_array[key];
});
console.log(main_array); // Desired result
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 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
}
})
i have this object, each key contains an index after the underscore at the end of it, so i can do something and try to gather each one with the same index together and get the expected obj, i don't know how to do it with underscore of even plain java-script
var obj = {
phoneNumber_0 : "2",
phoneNumber_1 : "0",
phoneType_0 : "Home",
phoneType_1 : "Work"
}
var expected = [
{number: '2', type: 'home'},
{number: '0', type: 'work'},
]
You could split the keys of the object for the name and for index. Then build a new object if necessary and assign the value of the actual property.
var object = { phoneNumber_0: "2", phoneNumber_1: "0", phoneType_0: "Home", phoneType_1: "Work" },
result = [];
Object.keys(object).forEach(function (k) {
var p = k.split('_');
result[p[1]] = result[p[1]] || {};
result[p[1]][p[0]] = object[k];
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I guess this will do what you have been looking for,
var obj = {
phoneNumber_0 : "2",
phoneNumber_1 : "0",
phoneType_0 : "Home",
phoneType_1 : "Work"
}
var finalArray = []
Object.keys(obj).map((key,index) => {
if (obj['phoneNumber_' + index] || obj['phoneType_' + index])
finalArray.push({ number: obj['phoneNumber_' + index], type:obj['phoneType_' + index]})
})
console.log(finalArray)
It would be your expected result
var obj = {
phoneNumber_0 : "2",
phoneNumber_1 : "0",
phoneType_0 : "Home",
phoneType_1 : "Work"
}
var expected = []
for(var key in obj){
if(key.indexOf('phoneNumber_') === 0){
var kn = key.replace('phoneNumber_', '')
expected.push({number: obj[key], type: (obj['phoneType_' + kn]||'').toLowerCase()})
}
}
console.log(expected)