I'm working on a project where I get an object in input like this one :
const obj = {
a: 'somestring',
b: 42,
c: {
d: 'foo',
e: 'bar'
},
f: [1, 2]
};
and I need to create some variables to get to this output :
const a = "somestring"
const b = 42
const c.d = "foo"
const c.e = "bar"
const f[0] = 1
const f[1] = 2
I got a result with this code :
for (const [k1, v1] of Object.entries(obj)) {
if (typeof v1 === "object") {
if (Array.isArray(v1)) {
for (const [k2, v2] of Object.entries(v1)) {
console.log(`const ${k1}[${k2}] = ${v2}`);
}
} else {
for (const [k2, v2] of Object.entries(v1)) {
console.log(`const ${k1}.${k2} = ${v2}`);
}
}
} else {
console.log(`const ${k1} = ${v1}`);
}
}
But when I get an object more complex like this one :
const obj = {
a: [
{
b: 'lorem'
},
{
c: 'ipsum'
}
],
d: {
e: {
f : 'foobar'
}
}
};
My output look like this :
const a[0] = [object Object]
const a[1] = [object Object]
const d.e = [object Object]
I can't find any relevant solutions. Is there a solution or npm package for this?
There is a feature called destructuring docs click here
This feature as the docs say will help you create new variables from a nested object.
Taking a object which is nested you can access its leaf values and assign them directly to vars like this:
const o = {
a: 'a',
b: {
c : 'c',
d: {
e: 'e'
}
}
};
const {a ,b : { c, d: {e} }} = o;
alert(a);
alert(c);
alert(e);
Edit: it works with arrays as well not objects only
You can do it with eval function in JS:
const obj = {
a: 'somestring',
b: 42,
c: {
d: 'foo',
e: 'bar'
},
f: [1, 2]
};
var log = console.log;
for (let key in obj) {
//log(key);
eval(`var ${key} = obj.${key}`);
}
log(a);
log(b);
log(c);
log(f);
I think you want something like this:
const obj = {
a: 'somestring',
b: 42,
c: {
d: 'foo',
e: 'bar'
},
f: [1, 2]
};
const parse = (obj, prefix = '', isArray=false) => {
Object.entries(obj).forEach(([k, v]) => {
if (typeof v === 'object') parse(v, `${k}`, Array.isArray(v))
else {
const value = (typeof v === 'string') ? `"${v}"` : v;
const before = isArray ? '[' : prefix ? '.' : '';
const after = isArray ? ']' : '';
console.log(`const ${prefix}${before}${k}${after} = ${value}`)
}
});
}
parse(obj);
Related
Here is the task
#param {object} ???
#returns {object} an object with the given object's values as keys, and keys as values. If there are duplicate values in the input object, only the first key-value pair should be used and subsequent pairs with the same value discarded.
2.Here is what i did code
What's wrong with it? How should i rework?
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
function swapPairs2(obj){
let newObject = {};
for(const key in obj){
let value = obj[key]
newObject[value] = key;
}
return newObject;
}
3.Here are the tests
test(swapPairs2(object5), { 1: "a", 2: "b", 3: "c" });
test(swapPairs2(object6), { 1: "a" });
4.Here is the error i got
I am supposed to get the first key-value pair, but a random return.
You can also reverse the entries.
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = obj => Object.fromEntries(
Object.entries(obj)
.reverse() // Keep the first, not the last
.map(entry => [entry[1], entry[0]]) // Reverse the key and vlaue
);
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Only add the value/key pairs, if the value doesn't already exist on newObject by checking with the in operator:
function swapPairs2(obj) {
const newObject = {};
for (const key in obj) {
const value = obj[key];
if(!(value in newObject)) {
newObject[value] = key;
}
}
return newObject;
}
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Another option is to use Array.reduce():
const swapPairs2 = obj =>
Object.entries(obj)
.reduce((acc, [k, v]) =>
v in acc
? acc
: { ...acc, [v]: k }
, {})
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
You can do it by taking the object keys and using the Array.reduce() method on the keys.
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = (obj) => Object.keys(obj)
.reduce((a, c) => (a[obj[c]] = a[obj[c]] ?? c, a), {});
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Or using the Array.reduce() method on the Object.entries()
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = obj => Object.entries(obj)
.reduce((acc, [key, val]) => (acc[val] = acc[val] ?? key, acc), {})
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
This question already has answers here:
One liner to flatten nested object
(19 answers)
Closed 1 year ago.
I am trying to achieve it Like a:1,b:2:,c:3,e:4,g:5,h:6
But not getting success.
Facing error this. But is the best way to do it.
const input = {
a: 1,
b: 2,
c: 3,
d: {
e: 4,
f: {
g: 5,
h: 6
}
}
}
const getValue = (values) => {
for (let i in Object.keys(values)) {
if (Object.keys(values[Object.keys(values)[i]]).length > 0) {
console.log('v', Object.keys(values)[i])
getValue(Object.keys(values)[i])
} else {
// console.log(Object.keys(values)[i],Object.values(values)[i])
}
}
}
getValue(input)
You can iterate through each key of object and for object value recursively call your getValue() function.
const input = { a:1, b:2, c:3, d:{ e:4, f:{ g:5, h:6 } } }
const getValue = (values) => {
for (const key of Object.keys(values)) {
if(typeof values[key] === 'object' && values[key] !== null) {
getValue(values[key]);
} else {
console.log(`${key}: ${values[key]}`);
}
}
}
getValue(input);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use recursion to get the desired result.
const input = {
a: 1,
b: 2,
c: 3,
d: {
e: 4,
f: {
g: 5,
h: 6,
},
},
};
const result = {};
function getValues(obj) {
for (let key in obj) {
if (typeof obj[key] !== `object`) result[key] = obj[key];
else getValues(obj[key]);
}
}
getValues(input);
console.log(result);
Edited : you can do something like this
const input = {a:1,b:2,c:3,d:{e:4,f:{g:5,h:6 }}}
Object.assign({}, ...function _flatten(o) { return [].concat(...Object.keys(o).map(k => typeof o[k] === 'object' ? _flatten(o[k]) : ({[k]: o[k]})))}(input))
//{a: 1, b: 2, c: 3, e: 4, g: 5, …}
you can see more details here
I'm trying to create an updated object from an existing object.
The sample object is:
// sample object
const testObj = {
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4
}
}
}
};
I want to create a new object from the above object with some concatenation of each value:
// expected object
const expectedObject= {
a: '1 a',
b: {
c: '2 a',
d: {
e: '3 a',
f: {
g: '4 a'
}
}
}
};
here is my sample code:
let expectedObject = {};
const newObject = object => {
Object.entries(object).forEach(([key, value]) => {
if (typeof value === "object") {
Object.keys(value).map(key => {
value[key] = value[key] + " a";
return value;
});
expectedObject[key] = value;
//return newTest;
} else {
expectedObject[key] = value;
return expectedObject;
}
});
return expectedObject;
};
console.log(newObject(testObj));
the outcome in console is:
{a: 1, b: {…}}
a: 1
b:
c: "2 a"
d: "[object Object] a"
__proto__: Object
__proto__: Object
I wanted to use recursion here and also tried it but no luck.
any help, thanks?
You could get a new object my mapping changed values and creating new objects.
function map(object, fn) {
return Object.fromEntries(Object
.entries(object)
.map(([k, v]) => [k, v && typeof v === 'object' ? map(v, fn) : fn(v)])
);
}
var object = { a: 1, b: { c: 2, d: { e: 3, f: { g: 4 } } } },
result = map(object, v => v + ' a');
console.log(result);
If you have arrays inside, you could add a check in advance and map the values.
const
map = fn => {
const iter = v => v && typeof v === 'object'
? Array.isArray(v)
? v.map(iter)
: Object.fromEntries(Object.entries(v).map(([k, v]) => [k, iter(v, fn)]))
: fn(v);
return iter;
};
var object = { a: 1, b: { c: 2, d: { e: 3, f: { g: 4, k: [5, 6] } } } },
addA = map(v => v + ' a'),
result = addA(object);
console.log(result);
This is simply a refactoring of the answer from #user633183. I like that approach a lot, but think it can be simplified by extracting two more reusable functions. This started as a comment on that answer, but I thought it would be better to be explicit.
const map = (f) => (a) =>
a.map(f)
const mapObj = (f) => (o) =>
Object .entries (o) .reduce ( (a, [k, v] ) => ({ ...a, [k]: f(v) }), {})
const traverse = (f) => (t) =>
Array.isArray(t)
? map (traverse (f)) (t)
: Object(t) === t
? mapObj (traverse (f)) (t)
: f (t)
const input =
{ a: [ 1, 11, 111 ], b: { c: 2, d: { e: [ 3, { f: { g: 4 } } ] } } }
const output =
traverse(x => `${x} a`) (input)
console.log(output)
mapObj can be written in many different ways. Here are two alternatives:
const mapObj = (f = identity) => (o = {}) =>
Object .fromEntries (Object .entries (o) .map (([ k, v ]) => [ k, f (v) ]))
const mapObj = (f = identity) => (o = {}) =>
Object .assign .apply (null, Object .entries (o) .map (([ k, v ]) => ({ [k]: f (v)
Here's an approach using a modification of the original code to demonstrate what needed to be changed in order to make it work. You had some things switched up reading the value and setting the new one. Also I'm using the spread operator to clone the object before modifying it.
const testObj = {
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4
}
}
}
};
const newObject = object => {
const clonedObj = { ...object };
const entries = Object.entries(clonedObj);
entries.forEach(([key, value]) => {
if (typeof value === "object") {
clonedObj[key] = newObject(value);
} else {
clonedObj[key] = value + " a";
}
});
return clonedObj;
};
console.log(newObject(testObj));
console.log(testObj); // prove that the original object hasn't changed
Here's a simple recursive technique. It is similar to Nina's but it preserves arrays, if present in the structure.
If the input, t, is an array, create a new array by traversing each array value, v, with the traversing function, f
(inductive) Otherwise t is not an array. If t is an object, create a new object from key value pairs, [ k, v ], by traversing each value, v, with the traversing function, f
(inductive) Otherwise t is not an array and t is not an object. This means t is either a primitive value, such as string, number, or null
Numbered comments below correspond to the explanation above -
const identity = x =>
x
const traverse = (f = identity, t = {}) =>
Array.isArray(t) // 1
? Array.from(t, v => traverse(f, v))
: Object(t) === t // 2
? Object.fromEntries(Object.entries(t).map(([ k, v ]) => [ k, traverse(f, v) ]))
: f (t) // 3
const input =
{ a: [ 1, 11, 111 ], b: { c: 2, d: { e: [ 3, { f: { g: 4 } } ] } } }
const output =
traverse(x => `${x} a`, input)
console.log(output)
Here is a solution using object-scan. It works by building the solution at the same time as the input is traversed.
// const objectScan = require('object-scan');
const testObj = { a: 1, b: { c: 2, d: { e: 3, f: { g: 4 } } } };
const cloneAndModify = (obj) => objectScan(['**'], {
breakFn: ({ property, value, isLeaf, context }) => {
if (property === undefined) {
return;
}
const ref = context[context.length - 1];
if (!(property in ref)) {
ref[property] = isLeaf ? `${value} a` : {};
}
context.push(ref[property]);
},
filterFn: ({ context }) => {
context.pop();
}
})(obj, [{}])[0];
const r = cloneAndModify(testObj);
console.log(r);
// => { b: { d: { f: { g: '4 a' }, e: '3 a' }, c: '2 a' }, a: '1 a' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan
In Javascript (ES6) have two objects with data.
const template = {
a: '',
b: '',
x: ''
}
This is the data object I will receive
const data = {
a: 'test',
b: 'test',
c: 'test'
}
How can I map the data from my received object to my template object without allowing values that are not present in the template object.
So the result should be this.
const result = {
a: 'test',
b: 'test',
x: ''
}
you can use a for...in loop :
const template = {
a: '',
b: ''
}
const data = {
a: 'test',
b: 'test',
c: 'test'
}
const result = {};
for (let k in template) {
result[k] = data[k];
}
console.log(result)
You could get the template object and the properties with the same keys from data.
const
template = { a: '', b: '', x: '' },
data = { a: 'test', b: 'test', c: 'test' },
result = Object.assign(
{},
template,
...Object.keys(template).map(k => k in data && { [k]: data[k] })
);
console.log(result);
Something like this:
let result = {};
const template = {
a: '',
b: ''
}
const data = {
a: 'test',
b: 'test',
c: 'test'
}
for (let prop in data) {
if(prop in template) result[prop] = data[prop];
}
console.log(result);
Just for fun you could use some Proxy magic :)
const template = {
a: '',
b: ''
}
const data = {
a: 'test',
b: 'test',
c: 'test'
}
const result = { ...new Proxy(data, {
ownKeys: () => Object.keys(template)
})
}
console.log(result)
const template = {
a: '',
b: ''
}
const data = {
a: 'test',
b: 'test',
c: 'test'
}
function setData(inputTemplate, inputData) {
outputObject = {}
for (var key in inputTemplate) {
if (inputData[key]) {
outputObject[key] = inputData[key];
}
}
return outputObject
}
console.log(setData(template, data))
You can use of Array.reduce to look at your object and only change the keys you are interested in. This method will also handle the case where the key you want to copy from data is not here. Also we have created a new object, we do not mutate the existing one.
Without mutation (new object)
const template = {
a: '',
b: '',
};
const data = {
a: 'test',
b: 'test',
c: 'test',
};
const ret = Object.keys(template).reduce((tmp, x) => {
tmp[x] = data[x] !== void 0 ? data[x] : tmp[x];
return tmp;
}, {
...template,
});
console.log(ret);
Mutating the object (use the old object)
const template = {
a: '',
b: '',
};
const data = {
a: 'test',
b: 'test',
c: 'test',
};
Object.keys(template).forEach((x) => {
template[x] = data[x] !== void 0 ? data[x] : template[x];
});
console.log(template);
You can simply loop on the keys of your template, and set the value with the data object with the same key.
const data = {
a: 'test',
b: 'test',
c: 'test'
}
const template = {
a: '',
b: ''
}
Object.keys(template).forEach((key) => template[key] = data[key])
console.log(template)
you can also use reduce
Example :
const template = {
a: '',
b: ''
}
const data = {
a: 'test',
b: 'test',
c: 'test'
}
const res = Object.keys(template).reduce((all, acc) => {
all[acc] = data[acc]
return all
}, {})
console.log(res)
need to create a shallow array of objects based on the elements of an array that is an object's value:
var obj = {
a: 1,
b: 'x',
c: 'z',
d: ['rr', 'qq']
};
var rec = [];
obj.d.forEach(function(e, i) {
rec.push({
d: e
})
});
console.log(rec);
But of course this only gets me
[ { d: 'rr' }, { d: 'qq' } ]
How to get to this in a new array of objects? -->
[ { a: 1,
b: 'x',
c: 'z',
d: 'rr' },
{ a: 1,
b: 'x',
c: 'z',
d: 'qq' } ]
The easiest way to get the desired result would be to use the map function (which maps elements of one array to a new array using a given mapping function). You can then create new objects re-using a, b, and c from the original object and d from the mapping function parameters:
var rec = obj.d.map(function(r) {
return {
a: obj.a,
b: obj.b,
c: obj.c,
d: r
};
});
obj.d.forEach(function(e) {
var item = {};
Object.keys(obj).forEach(function(key) {
item[key] = obj[key];
});
item.d = e;
rec.push(item);
});
But properties a, b, c can't be objects. Otherwise each item in the rec array will have the same reference.
Alternately, this works, but it is quite ugly:
var o = {
a: 1,
b: 'x',
c: 'z',
d: ['rr', 'qq']
};
var arr = [];
Object.keys(o).forEach(function(k) {
var val = o[k];
if (Array.isArray(val)) {
val.forEach(function(j) {
arr.push({[k] : j});
});
}
});
arr.forEach(function(obj) {
for (var p in o) {
var val = o[p];
if (!Array.isArray(val)) {
obj[p] = val
}
}
});
console.log(arr);