Can we assign an object key to another variable like this? [duplicate] - javascript

Given a JavaScript object, how can I convert it into an array of objects (each with key, value)?
Example:
var data = { firstName: 'John', lastName: 'Doe', email: 'john.doe#gmail.com' }
resulting like:
[
{ key: 'firstName', value: 'John' },
{ key: 'lastName', value: 'Doe' },
{ key: 'email', value: 'john.doe#gmail.com' }
]

var data = { firstName: 'John', lastName: 'Doe', email: 'john.doe#gmail.com' }
var output = Object.entries(data).map(([key, value]) => ({key,value}));
console.log(output);
Inspired By this post

Using map function
var data = { firstName: 'John', lastName: 'Doe', email: 'john.doe#gmail.com' };
var result = Object.keys(data).map(key => ({ key, value: data[key] }));
console.log(result);

You can just iterate over the object's properties and create a new object for each of them.
var data = { firstName: 'John', lastName: 'Doe', email: 'john.doe#gmail.com' };
var result = [];
for(var key in data)
{
if(data.hasOwnProperty(key))
{
result.push({
key: key,
value: data[key]
});
}
}

The previous answer lead me to think there is a better way...
Object.keys(data).map(function(key) {
return { key, value: data[key] };
});
or in ES6 using arrow functions:
Object.keys(data).map((key) => ({ key, value: data[key] }));

Just make your life easier and use es6 syntax with a map
var output = Object.keys(data).map(key => {
return {
key: key,
value: data[key]
};
})

var result = [];
for(var k in data) result.push({key:k,value:data[k]});

Or go wild and make the key and value keys customizable:
module.exports = function objectToKeyValueArray(obj, keyName = 'key', valueName = 'value') {
return Object
.keys(obj)
.filter(key => Object.hasOwnProperty.call(obj, key))
.map(key => {
const keyValue = {};
keyValue[keyName] = key;
keyValue[valueName] = obj[key];
return keyValue;
});
};

An alternative method for doing this that works on multi level objects and does not use recursion.
var output = []
var o = {
x:0,
y:1,
z:{
x0:{
x1:4,
y1:5,
z1:6
},
y0:2,
z0:[0,1,2],
}
}
var defer = [ [ o ,[ '_root_' ] ] ]
var _defer = []
while(defer.length){
var current = defer.pop()
var root = current[1]
current = current[0]
for(var key in current ){
var path = root.slice()
path.push(key)
switch( current[key].toString() ){
case '[object Object]':
_defer.push( [ current[key] , path ] )
break;;
default:
output.push({
path : path ,
value : current[key]
})
break;;
}
}
if(!defer.length)
defer = _defer.splice(0,_defer.length)
}
[
{ path: [ '_root_', 'x' ], value: 0 },
{ path: [ '_root_', 'y' ], value: 1 },
{ path: [ '_root_', 'z', 'y0' ], value: 2 },
{ path: [ '_root_', 'z', 'z0' ], value: [ 0, 1, 2 ] },
{ path: [ '_root_', 'z', 'x0', 'x1' ], value: 4 },
{ path: [ '_root_', 'z', 'x0', 'y1' ], value: 5 },
{ path: [ '_root_', 'z', 'x0', 'z1' ], value: 6 }
]

const array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
const obj = Object.fromEntries(array.map(item => [item.key, item.value]));
console.log(obj);

I would say to use npm package flat.
works amazing for nested objects and arrays.
var flatten = require('flat')
flatten({
key1: {
keyA: 'valueI'
},
key2: {
keyB: 'valueII'
},
key3: { a: { b: { c: 2 } } }
})
// {
// 'key1.keyA': 'valueI',
// 'key2.keyB': 'valueII',
// 'key3.a.b.c': 2
// }

const array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
const obj = Object.fromEntries(array.map(item => [item.key, item.value]));
console.log(obj);

Related

Create nested object from serializeArray

I'd like to create this structure:
{
"officine_type": "Pharmacie",
"officine_value": 2002626,
"declared_lines": [
{
"ean": 3578835501148,
"qty": 1
},
{
"ean": 3578835502671,
"qty": 2
}
],
"other_value": "my other value"
}
From a serializeArray() with this output:
0: {name: 'declared_lines.0.ean', value: '3578835502244'}
1: {name: 'declared_lines.0.qty', value: '4'}
2: {name: 'declared_lines.1.ean', value: '3578835502220'}
3: {name: 'declared_lines.1.qty', value: '1'}
4: {name: 'declared_lines.2.ean', value: ''}
5: {name: 'declared_lines.2.qty', value: '0'}
6: {name: 'officine_type', value: 'Pharmacy'}
7: {name: 'officine_value', value: '2000461'}
8: {name: 'other_value', value: ''}
I'm struggling on how to push sub-objects in declared_lines
Right now i have this:
let formData = form.serializeArray();
for (let i = 0; i < formData.length; i++) {
if (formData[i]['name'].indexOf('declared_lines') !== 1) {
let inputName = formData[i]['name'].split('.');
let namespace = inputName[0];
let n = inputName[1];
let key = inputName[2];
let subObj = {};
let current = 'declared_lines['+i+']';
let previous = 'declared_lines['+(i-1)+']';
if (obj.hasOwnProperty(namespace) === false) {
obj[namespace] = [];
}
}
obj[formData[i]['name']] = formData[i]['value'];
}
My brain won't go further :(
You could take the name and split it by dot for the path of the new object and the value and build a new object with the given information.
In setValue, the reduce callback checks if the next key is a stringed numerical value and takes an array as default object instead of an object.
function setValue(object, path, value) {
const last = path.pop();
path
.reduce((o, k, i, kk) => o[k] ??= (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {}), object)
[last] = value;
return object;
}
const
data = [{ name: 'declared_lines.0.ean', value: '3578835502244' }, { name: 'declared_lines.0.qty', value: '4' }, { name: 'declared_lines.1.ean', value: '3578835502220' }, { name: 'declared_lines.1.qty', value: '1' }, { name: 'declared_lines.2.ean', value: '' }, { name: 'declared_lines.2.qty', value: '0' }, { name: 'officine_type', value: 'Pharmacy' }, { name: 'officine_value', value: '2000461' }, { name: 'other_value', value: '' }],
result = data.reduce(
(object, { name, value }) => setValue(object, name.split('.'), value),
{}
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Object destructuring and array.reduce can make your code more readable, try:
let formData = [
{name: 'declared_lines.0.ean', value: '3578835502244'},
{name: 'declared_lines.0.qty', value: '4'},
{name: 'declared_lines.1.ean', value: '3578835502220'},
{name: 'declared_lines.1.qty', value: '1'},
{name: 'declared_lines.2.ean', value: ''},
{name: 'declared_lines.2.qty', value: '0'},
{name: 'officine_type', value: 'Pharmacy'},
{name: 'officine_value', value: '2000461'},
{name: 'other_value', value: ''}
];
let output = formData.reduce((acc,cur) => {
let { name, value } = cur;
if(name.indexOf('declared_lines') === -1){
acc[name] = value;
} else {
let [namespace, n, key] = name.split('.');
if(!acc[namespace]) acc[namespace] = [];
if(!acc[namespace][n]) acc[namespace][n] = {};
acc[namespace][n][key] = value;
}
return acc;
}, {});
console.log(output);
In this case reduce starts with an empty object and it loops over your array to process each element (cur).

How to convert array to object by key?

Suppose I got this array:
const users =[
{
id:1,
name:'bob',
},
{
id:2,
name:'sally',
},
{
id:3,
name:'bob',
age:30,
}
];
And I want to use any key(in this case 'name' ) to return an object :
{
bob:[
{
id:1,
name:'bob',
},
{
id:3,
name:'bob',
age:30,
}
],
sally:[
{
id:2,
name:'sally',
}
],
}
I tried this:
const go = (A,key) =>{
return A.reduce((o, key) => ({ ...o, [key]:o }), {})
}
export default go;
But this returns:
{ '[object Object]': { '[object Object]': { '[object Object]': {} } } }
If the key is not present omit from the result. It should not mutate the original array though. How can I perform this kind of conversion?
With the approach you have, a new array is not instantiated in case the key is not yet present in the object.
This will work:
const result = users.reduce((a, v) => {
a[v.name] = a[v.name] || [];
a[v.name].push(v);
return a;
}, {});
Complete snippet wrapping this logic in a function:
const users = [{
id: 1,
name: 'bob',
}, {
id: 2,
name: 'sally',
}, {
id: 3,
name: 'bob',
age: 30,
}];
const go = (input, key) => input.reduce((a, v) => {
a[v[key]] = a[v[key]] || [];
a[v[key]].push(v);
return a;
}, {});
console.log(go(users, 'name'));
If you really want to cram it into a one-liner, this will also work, by either spreading the already existing array, or an empty one:
const result = users.reduce((a, v) => ({...a, [v.name]: [...a[v.name] || [], v]}), {});
Complete snippet wrapping this logic in a function:
const users = [{
id: 1,
name: 'bob',
}, {
id: 2,
name: 'sally',
}, {
id: 3,
name: 'bob',
age: 30,
}];
const go = (input, key) => input.reduce((a, v) => ({...a, [v[key]]: [...a[v[key]] || [], v]}), {});
console.log(go(users, 'name'));
You were close but the key attribute in this case was each value (eg: { id: 1, name: 'bob' }) so the string representation is [object Object] which is why all the keys are that. Based off what you said, you want to use key.name as the property and set it's value as [key]. (I renamed key to arr in my example since it's the array value).
So this would be something like { ...o, [arr.name]: [arr] }
Because there can be an existing value, it adds a bit of complexity which is what [...(obj[arr.name] || []), arr] is doing. It's looking up the existing value (or defaulting to an empty array) and spreading those values and adding the new value.
const users = [{
id: 1,
name: 'bob',
},
{
id: 2,
name: 'sally',
},
{
id: 3,
name: 'bob',
age: 30,
}
];
const transform = (input, keyName) => {
return input.reduce((obj, arr) => ({ ...obj,
[arr[keyName]]: [...(obj[arr[keyName]] || []), arr]
}), {})
}
console.log(transform(users, 'name'))
console.log(transform(users, 'id'))

How to merge 3 javascript object with modified value

I have 3 objects like
[
const arr = [
{name:'ABC', value:123},
{name:'ABC', value:456},
{name:'ABC',value:789},
{name:'DEF',value:9999},
name:'DEF', value:0000}
]
i want output like
updatedArr = [
{name:'ABC', value:123, value1:456, value2:789}
{name:'DEF', value:9999, value1:0000}
]
any kind of links regarding this will be also helpful.
You could use reduce method to create an object and then Object.values to get an array of values.
const arr = [{name:'ABC', value:123},{name:'ABC', value:456},{name:'ABC',value:789},{name:'DEF',value:9999},{name:'DEF', value:0000}]
const res = arr.reduce((r, e) => {
if(!r[e.name]) r[e.name] = {...e}
else {
let {name, ...rest} = r[e.name];
r[e.name][`value${Object.keys(rest).length}`] = e.value
}
return r;
}, {});
console.log(Object.values(res))
const arr = [{
name: 'ABC',
value: 123
},
{
name: 'ABC',
value: 456
},
{
name: 'ABC',
value: 789
},
{
name: 'DEF',
value: 9999
},
{
name: 'DEF',
value: 0000
}
]
const res = Object.values(arr.reduce((acc, item) => {
if (!acc[item.name]) {
acc[item.name] = item;
} else {
acc[item.name]['value' + (Object.keys(acc[item.name]).length - 1)] = item.value;
}
return acc;
}, {}));
console.log(res)
use object assignation:
Object.assign(ob1,ob2);

Override all keys of an object but its id

I have a similar object as this one but it has quite more keys. I want to update all of its keys but id. I can do so manually. But I think it is not the best way.
const o = {
name: "unknow",
key: "key"
value: "value"
id ": 12
}
How can I update/override all keys of an object but id?
Update
The two object has the same keys. But their keys have different value. I need to update all keys of the first object excluding its id.
I suspect that you're looking for something like assignBut: it sets properties of ob on oa but the specified one:
const assignBut = (prop, oa, ob) => {
for (let key of Object.keys(ob))
// Check that I also verify that the property
// to set should be part of "oa" object. This
// prevents adding new properties: it just updates
// existing ones.
if (key !== prop && oa.hasOwnProperty(key))
oa[key] = ob[key]
}
const oa = {
name: "unknow",
key: "key",
value: "value",
id: 12
}
const ob = {
name: "xxx",
key: "yyy",
value: "zzz",
other: "aaa",
yetAnother: 289,
id: 15
}
assignBut('id', oa, ob)
console.log(oa)
Another approach to omit a given property
One may take advantage of destructuring and computed property names to omit the whole given property so the for..of just needs to check that each property from ob is present in oa to set it.
Also, one may save the check to verify that a property from ob exists in oa performing an intersection of oa and ob keys:
const oa = {
name: "unknow",
key: "key",
value: "value",
id: 12
}
const ob = {
name: "xxx",
key: "yyy",
value: "zzz",
other: "aaa",
yetAnother: 289,
id: 15
}
const intersect = (xs, ys) => xs.filter(x => ys.includes(x))
const assignBut = (prop, oa, {
[prop]: omitted,
...ob
}) => {
const sharedKeys = intersect(Object.keys(oa), Object.keys(ob))
for (let key of sharedKeys)
oa[key] = ob[key]
}
assignBut('id', oa, ob)
console.log(oa)
You can iterate through Object.keys like below -
const o = {
name: "unknow",
key: "key",
value: "value",
id : 12
};
Object.keys(o).forEach((key)=>{
if(key !=="id"){
console.log(o[key]) //value
}
}
);
Following approach is based on lodash. If you are not comfortable using a library, please ignore.
Benefit of omit is that you can pass an array of keys and ignore multiple keys.
There is also a function called pick where you can only pick certain properties you need.
_.omit
const o = { name: "unknow", key: "key", value: "value", id: 12 }
const props = { name: "foo", key: "key2", value: "bar", id: 15 };
const final = _.assign({}, o, _.omit(props, 'id'));
console.log(final)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
_.pick
const o = { name: "unknow", key: "key", value: "value", id: 12 }
const props = { name: "foo", key: "key2", value: "bar", id: 15, test: 'abc', hello: 'world' };
const final = _.assign({}, o, _.pick(props, ['name', 'key', 'value']));
console.log(final)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
pure js implementation
const o = { name: "unknow", key: "key", value: "value", id: 12 }
const propsOmit = { name: "foo", key: "key2", value: "bar", id: 15 };
const propsPick = { name: "foo", key: "key2", value: "bar", id: 15, test: 'abc', hello: 'world' };
const finalOmit = Object.assign({}, o, omit(propsOmit, 'id'));
const finalPick = Object.assign({}, o, omit(propsPick, ['id', 'test', 'hello']));
console.log(finalOmit)
console.log(finalPick)
function omit(obj, ignoreKeys) {
if (!Array.isArray(ignoreKeys)) {
ignoreKeys = [ ignoreKeys ];
}
const copy = Object.assign({}, obj);
ignoreKeys.forEach((k) => delete copy[k]);
return copy;
}
function pick(obj, selectKeys) {
if (!Array.isArray(selectKeys)) {
selectKeys = [ selectKeys ];
}
const copy = {};
ignoreKeys.forEach((k) => copy[k] = obj[k]);
return copy;
}
References:
_.assign
_.omit
_.pick

How to convert an array to an object in Lodash?

I have:
{
dis:{["String1","String2","String3"]},
par:"pony"
}
And I want to turn it into this:
[
{ name: 'String1', value: "pony" },
{ name: 'String2', value: "pony" },
{ name: 'String3', value: "pony" }
]
If you change to valid js data you can do this with reduce()
var obj = {
dis: ["String1", "String2", "String3"],
par: "pony"
}
var result = obj.dis.reduce(function(r, e) {
r.push({name: e, value: obj.par});
return r;
}, []);
console.log(result)
You can do it easily, but beware you have double parentheses (mustaches and square bracket).
var
data = {
dis: ["String1","String2","String3"],
par: "pony"
},
result = [];
for (var index in data.dis)
result.push({ name: data.dis[index], value: data.par}
you can find the fiddle here.
You can do it using Array.protoype.map:
var obj = {
dis:["String1","String2","String3"],
par:"pony"
};
var arrOfObj = obj.dis.map(function(name) {
return {
name: name,
value: obj.par
}
});
console.log(arrOfObj)
Or lodash's _.map:
var obj = {
dis:["String1","String2","String3"],
par:"pony"
};
var arrOfObj = _.map(obj.dis, function(name) {
return {
name: name,
value: obj.par
}
});
console.log(arrOfObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>

Categories