Let's say I have the following array:
['product' , 'model', 'version']
And I would like to have an object such as:
{
product: {
model: {
version: {
}
}
}
}
However, that array is dynamic so it could have 2, 3 or fewer more items.
How can this be achieved in the most efficient way?
Thanks
Just turn it inside out and successively wrap an inner object into an outer object:
const keys = ['product', 'model', 'version'];
const result = keys.reverse().reduce((res, key) => ({[key]: res}), {});
// innermost value to start with ^^
console.log(result);
You can also do it with Array.prototype.reduceRight:
const result = ['product','model','version'].reduceRight((all, item) => ({[item]: all}), {});
console.log(result);
If I understood request correctly, this code might do what you need:
function convert(namesArray) {
let result = {};
let nestedObj = result;
namesArray.forEach(name => {
nestedObj[name] = {};
nestedObj = nestedObj[name];
});
return result;
}
console.log(convert(['a', 'b', 'c']));
Related
Let's say I have the following array:
['product' , 'model', 'version']
And I would like to have an object such as:
{
product: {
model: {
version: {
}
}
}
}
However, that array is dynamic so it could have 2, 3 or fewer more items.
How can this be achieved in the most efficient way?
Thanks
Just turn it inside out and successively wrap an inner object into an outer object:
const keys = ['product', 'model', 'version'];
const result = keys.reverse().reduce((res, key) => ({[key]: res}), {});
// innermost value to start with ^^
console.log(result);
You can also do it with Array.prototype.reduceRight:
const result = ['product','model','version'].reduceRight((all, item) => ({[item]: all}), {});
console.log(result);
If I understood request correctly, this code might do what you need:
function convert(namesArray) {
let result = {};
let nestedObj = result;
namesArray.forEach(name => {
nestedObj[name] = {};
nestedObj = nestedObj[name];
});
return result;
}
console.log(convert(['a', 'b', 'c']));
I have an object like this
{
metadata: {
correlationId: 'b24e9f21-6977-4553-abc7-416f8ed2da2d',
createdDateTime: '2021-06-15T16:46:24.247Z'
}
}
and I have an array of the properties I wanna access
[metadata, correlationId]
how can I dynamically access the property on the object?
like
keys.forEach((key) => {
object[key][key2] ???
})
it needs to be dynamic since I don't know how deep we need to access the object
Here is a solution without recursion:
const myObj = {
a: {
b: {
c: "I'm the target"
}
}
}
const keys = ['a', 'b', 'c'];
let result = myObj;
for (const key of keys) {
result = result[key];
}
console.log(result);
Or with recursion:
const finder = (obj, keys, index = 0) => {
const result = obj[keys[index++]];
if (!result) {
return obj;
}
return finder(result, keys, index);
}
console.log(finder(myObj, keys));
This is pretty similar to Accessing nested JavaScript objects and arrays by string path, except with one fewer step - you already have the keys you need in the form of an array. .reduce and access the next nested value in each iteration.
const obj = {
metadata: {
correlationId: 'b24e9f21-6977-4553-abc7-416f8ed2da2d',
createdDateTime: '2021-06-15T16:46:24.247Z'
}
};
const keys = ['metadata', 'correlationId'];
const result = keys.reduce((a, key) => a[key], obj);
console.log(result);
This is my idea to solve your problem. Tell me, if is ok for you.
let x = {
metadata: {
correlationId: 'b24e9f21-6977-4553-abc7-416f8ed2da2d',
createdDateTime: '2021-06-15T16:46:24.247Z'
}
}
let fun = x => typeof x === 'string' ? console.log(x) : Object.keys(x).map( y => fun(x[y]));
fun(x);
I've read this answer on SO to try and understand where I'm going wrong, but not quite getting there.
I have this function :
get() {
var result = {};
this.filters.forEach(filter => result[filter.name] = filter.value);
return result;
}
It turns this :
[
{ name: "Some", value: "20160608" }
]
To this :
{ Some: "20160608" }
And I thought, that is exactly what reduce is for, I have an array, and I want one single value at the end of it.
So I thought this :
this.filters.reduce((result, filter) => {
result[filter.name] = filter.value;
return result;
});
But that doesn't produce the correct result.
1) Can I use Reduce here?
2) Why does it not produce the correct result.
From my understanding, the first iteration the result would be an empty object of some description, but it is the array itself.
So how would you go about redefining that on the first iteration - these thoughts provoke the feeling that it isn't right in this situation!
Set initial value as object
this.filters = this.filters.reduce((result, filter) => {
result[filter.name] = filter.value;
return result;
},{});
//-^----------- here
var filters = [{
name: "Some",
value: "20160608"
}];
filters = filters.reduce((result, filter) => {
result[filter.name] = filter.value;
return result;
}, {});
console.log(filters);
var filters = [{
name: "Some",
value: "20160608"
}];
filters = filters.reduce((result, {name, value}= filter) => (result[name] = value, result), {});
console.log(filters);
Since 2019 (ES2019) you can go with Object.fromEntries() but you need to map to array first.
const filtersObject = Object.fromEntries(filters.map(({ name, value }) => [name, value])
I'm fetching json data with ajax. Then I want to output it in Griddle using griddle-react. The problem is I cannot convert my array to a Griddle readable array.
After the ajax fetch i made a callback function:
function convert(obj) {
console.log(obj);
Object.keys(obj).forEach(function (key) {
let format = JSON.stringify(obj[key]);
console.log(format);
self.setState(() => ({ data: key[format] }));
});
}
The first console.log output looks like this:
{
{
"BTC": {
"opening_price": "9845000",
"closing_price": "9967000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9928071.5654",
"units_traded": "7242.04659594",
"volume_1day": "7242.04659594",
"volume_7day": "73491.92898643",
"buy_price": "9967000",
"sell_price": "9968000"
},
}
}
My functions makes it look like this: (second console.log):
{
"opening_price": "9846000",
"closing_price": "9965000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9929422.0905",
"units_traded": "7200.46713802",
"volume_1day": "7200.467F13802",
"volume_7day": "73395.33311647",
"buy_price": "9959000",
"sell_price": "9964000"
}
I want it to convert to the following array, basically adding the name item, and thereafter Griddle can read it:
{
"name": "BTC",
"opening_price": "9845000",
"closing_price": "9967000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9928071.5654",
"units_traded": "7242.04659594",
"volume_1day": "7242.04659594",
"volume_7day": "73491.92898643",
"buy_price": "9967000",
"sell_price": "9968000"
},
What I'm doing wrong here? I'm sure its pretty close to what I want, but I can't figure it out at this point.
You can use Object.entries to get the keys and values. Use Object.assign to make new objects
var obj = {
"BTC": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"}
}
var newObj = Object.entries(obj).reduce((c, [i, v]) => Object.assign(c, {name: i}, v), {});
console.log(newObj);
If you have several keys, you can use map
var obj = {
"BTC": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"},
"OTH": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"},
}
var newArr = Object.entries(obj).map(([i, v]) => Object.assign({}, {name: i}, v));
console.log(newArr);
Without including date property
var obj = {
"KNC": {"opening_price": "2731","closing_price": "2788","min_price": "2693","max_price": "2849","average_price": "2790.5368","units_traded": "3178032.25814499211673","volume_1day": "3178032.25814499211673","volume_7day": "110687333.315264505902311000","buy_price": "2783","sell_price": "2788"},
"date": "1525269153470"
}
var newObj = Object.entries(obj).reduce((c, [i, v]) => i !== 'date' ? Object.assign(c, {name: i}, v) : c, {});
console.log(newObj);
Can you update your function to have this line in it?
obj[key]["name"] = key
function convert(obj) {
console.log(obj);
Object.keys(obj).forEach(function (key) {
obj[key]["name"] = key;
let format = JSON.stringify(obj[key]);
console.log(format);
//self.setState(() => ({ bithumbData: key[format] }));
});
}
function convert(obj){
var parentKey = Object.keys(obj)[0];//Getting parent first element key
obj = obj[parentKey];
var newObj = {}; //Creating new empty jason object
newObj['name'] = parentKey; //key apply as name element to new jason object
for(var key in obj) //looping each child element
newObj[key] = obj[key]; //child applying to new jason object
return newObj;
}
console.log(JSON.stringify(convert(obj)));
I'm following a course online and one of the challenges is this:
Write a function called extractKey which accepts two parameters, an array of objects, and the name of a key and returns an array with just the values for that key: You must use reduce.
extractKey([{name: "Elie", isInstructor:true},{name: "Tim", isInstructor:true},{name: "Matt", isInstructor:true}], "name");
// ["Elie", "Tim", "Matt"]
I thought I could do something like this:
function extractKey(arr, key) {
arr.reduce(function(a, b) {
console.log(a.push(b[key]))
}, [])
}
But its returning 1. I have a general idea of pushing each value into the empty array, but when console logging each value, a will return undefined at the next accumulator.
If you have to use reduce then I'd combine it with concat like this.
var arr = [{
name: "Elie",
isInstructor: true
}, {
name: "Tim",
isInstructor: true
}, {
name: "Matt",
isInstructor: true
}]
function extractKeys(array, key) {
return array.reduce((acc, obj) => {
return acc.concat(obj[key])
}, [])
}
console.log(extractKeys(arr, 'name'))
If you use reduce (not really neccessary here), you need to pass on the accumulator:
function extractKey(arr, key) {
arr.reduce(function(acc, el) {
console.log(a.push(el[key]))
return acc; // <--
}, [])
}
Alternatively a good old for loop might be easier to understand:
function extractKey(arr, key){
const result = [];
for(const el of arr)
result.push(el[key]);
return result;
}
Finally you also might use map instead and currying to beautify it:
const extract = key => obj => obj[key];
const result = original.map(extract("name"));
you were very close but with reduce you have to return the value after every iteration of your callback since only the accumulator's value is saved
function extractKey(arr, key) {
arr.reduce(function(a, b) {
a.push(b[key])
console.log(a)
return a;
}, []);
}