I am trying to convert all elements of a given key in a list of objects. The specific change is to convert an generic object to a Long object with the same values.
Input:
[obj1, obj2, obj3, ...]
Where each object looks like:
{
key1: value1, // value1 is an object
key2: value2
}
So the goal here is to get a very similar array, but where key1 is transformed from just object to a long object, in my example incremented by one.
Output:
[obj1, obj2, obj3]
Where each object is:
{
key1: value1, // value1 is now a Long object
key2: value2
}
I tried with mapping over the array and then spreading over the objects entries, but did not succeed.
Any help would be highly appreciated.
You don't really need to map here, unless you want to create one more new array. Simple loop would be enough, just update key1 or each object:
[obj1, obj2, obj3].forEach(obj => {
obj.key1 = obj.key1 + 1
})
Since the array holds object - any modification to object reflect the actual input being passed. You need to make a copy of your object and perform the logic.
Your logic,
var input = [obj1, obj2, obj3];
var output = input.map(function(obj){
obj.key1 = obj.key1 + 1;
return obj;
});
console.log(input[0]===output[0]); //true
Solution:
var output = input.map(function(obj){
var _objCopy = Object.assign({}, obj);
_objCopy.key1 = _objCopy.key1 + 1;
return _objCopy;
});
console.log(input[0]===output[0]); //false
how about dynamically first key of any object es6 way
const myObject0 = {
'foo1': { name: 'myNam1' },
'foo2': { name: 'myNam2' }
};
const myObject1 = {
'yo': { name: 'myNam1' },
'boh': { name: 'myNam2' }
};
[myObject0, myObject1].forEach(obj => {
let getFirstKey = Object.keys(obj)[0];
getFirstKey = getFirstKey + 1;
console.log(getFirstKey);
});
Thanks for all the answers guys.
I ended up with the following:
Given the input
[
{
key1: value1, // value1 is an object
key2: value2
},
{
key1: value1, // value1 is also an object
key2: value2
}
]
Solution:
I ended up with,
const testvar = [obj1, obj2, obj3].map((obj) => {
return {
...obj,
key1: new Long.fromValue(obj.key1)
}
});
console.log(testvar);
Which gives the output
[
{
key1: value1, // value1 is now a Long object
key2: value2
},
{
key1: value1, // value1 is also now a Long object
key2: value2
}
]
Related
I'm not totally sure if I'm using the correct terminology or not, I'm relatively new to node.
I have two JSON objects
const objA = {
key1: value1
...
}
const objB = {
key2: value2
...
}
that I want to combine into one while keeping the two object names, so it would look a bit like:
const newObj = {objA: { key1: value1,...}, objB: { key2: value2,...}}
So far in my research I've found Object.assign(objA,objB) which just combines them as newObj = {key1: value1, key2: value2, ...}
Is there a way to do what I want?
const newObj = {objA, objB};
You can assign them into new object like above.
Just putting it out there as a reference if you wanted to combine the key and values from both objects into one you could always use spread syntax if you decide to not go with a multi-level object:
const objA = {
key1: "value1"
}
const objB = {
key2: "value2"
}
const objCombined = {...objA, ...objB }
console.log(objCombined)
I was trying to normalize a very deeply nested JSON which contains all possible ways JSON can be created. A part of JSON can be seen in below code snippet.
What is my end goal
I am converting the nested JSON into a simple JS object like below
{
key1: value,
key2: value,
...
}
Problem i faced with the below solution is that when it comes to Objects with values as array
i failed to find a way to see its key values.
if you run below code
key4,key5, key6 wont get displayed with the console.log only its value gets printed.
key1 -- values
key2 -- values
key3 -- value3
0 --
0 -- some_value
Code snippet
const req = {
request: {
results: {
key1: 'values',
results: [
{
key2: 'values',
},
],
},
params: {
key3: 'value3',
query: {
key4: [''],
key5: ['123456'],
key6: ['some_value'],
},
},
},
};
function normaliseJSON(obj) {
for (let k in obj) {
if (obj[k] instanceof Object) {
normaliseJSON(obj[k]);
} else {
console.log(`${k} -- ${obj[k]}`);
}
}
}
normaliseJSON(req);
Is there any way to get the keys of key4,5,6 ?
also open to any other solution to normalise such JSON
The reason your recursion goes inside the array is since ['123456'] instanceof Object is true in javascript (typeof(['asd']) also gives "object"). To check if something is an array have to check with Array.isArray(something)
In template literals when you try to embed an array eg ...${['123456']} in the end it will show as ...123456 without the brackets. Therefore in situation of Arrays need to JSON.stringify(arr)
There may be better ways of doing this but I created a function called arrayHasObject which checks if an array has object elements. This was to catch the inner results array and ignore key4,key5 and key6.
The recursion will happen if obj[k] is an object and not an array or if obj[k] is an array and it has an object element.
Since recursion is hard to visualize I recommend https://pythontutor.com/ . It is mostly for Python but works for JS as well. It can help you visualize these things and to find where things go wrong
Ofcourse the way I have written it will break if something like key4: [{a:'abc'}] since arrayHasObject gives true for this. Maybe will need to change the function accordingly.
function arrayHasObject(arr) {
return arr.some((x) => typeof(x)==='object' && !Array.isArray(x))
}
const req = {
request: {
results: {
key1: 'values',
results: [
{
key2: 'values',
},
],
},
params: {
key3: 'value3',
query: {
key4: [''],
key5: ['123456'],
key6: ['some_value'],
},
},
},
};
function normaliseJSON(obj) {
for (let k in obj) {
if ((obj[k] instanceof Object && !Array.isArray(obj[k])) || (Array.isArray(obj[k]) && arrayHasObject(obj[k]))) {
normaliseJSON(obj[k]);
} else {
if (Array.isArray(obj[k])){
console.log(`${k} -- ${JSON.stringify(obj[k])}`);
}
else{
console.log(`${k} -- ${obj[k]}`);
}
}
}
}
normaliseJSON(req);
I have a key value pair:
`{good: 'value1', key2: 'value2': key3: 'value3'}
I want to convert it as the following:
[{key: 'good', value:'value1'}, {key: 'key2', value: 'value2'}, {key: 'key3', value: 'value3']
So far, I am able to convert them into an array with Object.entries, but I am unable to get my desired result.
There exists a method Object.entries that turns object into list of keys and values already, mapping it to match your required format should not be difficult.
const data = {good: 'value1', key2: 'value2', key3: 'value3'};
const result = Object.entries(data).map(([key, value]) => ({key, value}))
console.log(result)
You can do it like this:
const data = {good: 'value1', key2: 'value2', key3: 'value3'};
const result = [];
Object.keys(data).forEach(key => {
result.push({key, value: data[key]})
})
console.log(result)
To transform arrays, javascript provides a variety of array methods. map, foreach, reduce. etc. (Read more)
Object.entries( data ) converts your object into an array of arrays where each inner array is a key-value pair like this
[ [key1, value1], [key2, value2] ....]. (Read More)
Your usecase:
const data = { good: 'value1', key2: 'value2', key3: 'value3' };
const entries = Object.entries(data);
// [ ["good","value1"], ["key2","value2"],["key3","value3"] ]
// Map those entries to your desired form.
const results = entries.map( entry => ({ key: entry[0], value: entry[1] }) ) ;
// Or leverage the destructuring fetaure
// const results = entries.map( ([key, value]) => ({ key, value }) ) ;
console.log(results)
In case if you are interested in fast solution:
type Values<T> = T[keyof T]
type Mapper<T> = {
[Prop in keyof T]: { key: Prop, value: T[Prop] }
}
type Convert<T> = Array<Values<Mapper<T>>>
function convert<
Prop extends string,
Value extends string,
Obj extends Record<Prop, Value>
>(obj: Obj): Convert<Obj>
function convert<
Prop extends string,
Value extends string,
Obj extends Record<Prop, Value>
>(obj: Obj) {
const result: {
key: Extract<keyof Obj, string>;
value: Obj[Extract<keyof Obj, string>];
}[] = []
for (let prop in obj) {
result.push({
key: prop,
value: obj[prop]
})
}
return result
}
const result = convert({ good: 'value1', key2: 'value2', key3: 'value3' })
const first = result[0]
if (first.key === 'good') {
// {
// key: "good";
// value: "value1";
// }
first
}
Cons:
convert function creates internal result variable and mutates it. It is possible to use recursion instead of mutation result but I'm not sure this trade of worth it.
Pros
Faster than entries & map
Convert types maps type of argument to the type you want to achieve but only in type scope, whereas function maps argument in runtime scope.
If performance is not critical, you probably should stick with other solution where Object.entries is used
I have a object array and would like to get key and value by iterating though it, however I only get 0, 1 as index. anyone know why?
const vairable = [{key1: "value1"}, {key2: "value2"}]
Object.keys(vairable).forEach((i: any) => {
console.log(i); # get 0 and 1, I would like to have key1, key2
});
Object.keys gives the indices of the array itself, not the objects in the values. Iterate over the values and explore them:
const variable = [{key1: "value1"}, {key2: "value2"}];
for (const value of variable) {
const firstKey = Object.keys(value)[0];
console.log(firstKey);
}
Please try like this.
const vairable = [{key1: "value1"}, {key2: "value2"}]
vairable.forEach(item =>{
for (const [key, value] of Object.entries(item)){
console.log(key , value)
}
})
it will output :
key1 value1
key2 value2
How about this: Loop through array:
const vairable = [{key1: "value1"}, {key2: "value2"}]
for(let e of vairable) {
console.log(Object.keys(e))
}
The Object.keys method work on the Object not on the Arrays. If you want a loop through an Object, Then it will work fine like below,
const keys = {key1: "value1", key2: "value2"};
Object.keys(keys).forEach((key) => {
console.log(key);
});
I am trying to copy a object to another by comparing it's key. according to me the key can be nested any of the object node. still I am require to copy them in another object by just comparing their key.
they object key in any level in the object tree.
Is this possible?
here is my try:
var extend = function (original, context, key) {
for (key in context)
if (context.hasOwnProperty(key))
if (Object.prototype.toString.call(context[key]) === '[object Object]')
original[key] = extend(original[key] || {}, context[key]);
else
original[key] = context[key];
return original;
};
var firstObject = {
key1 : 'ar',
key2 : 'value2',
address:{
"street" : "D15 Road"
"sub":{"name":"Stockoverflow"}
}
};
var secondObject = {
name:"",
street:"",
key3 : 'value3',
key4 : 'value4'
};
var x = extend(secondObject, firstObject )
console.log( 'extend', x );
In my above try, still the street:"", name:"" not updated.
This should do the trick:
const source = {
key1: 'a',
common1: 'value1',
a: {
b: {
c: {
common2: 'value2'
}
}
}
};
const dest = {
key2: 'b',
common1: null,
common2: null
};
function extend(dest, source) {
Object.entries(source).forEach(([key, value]) => {
if (typeof value === 'object') {
extend(dest, value);
} else if (dest.hasOwnProperty(key)) {
dest[key] = value;
}
});
}
extend(dest, source);
console.log(dest);
Basically, looping through them you only have two options: it's an object or it's key matches.
If it is an object, we just recursively call extend. If it's key matches, then we set the value.
If you want to be able to do this with objects as values (i.e., common1 could be an object instead of a primitive), just switch the two in the if statement.