I have a set which needs to be converted into an object with the set's unique values as the object keys and an empty string as each element's value in the object.
Here is the set I'm working with:
const uom = new Set(['inches', 'centimeters', 'yards', 'meters']);
I've tried this:
const uomObj = {...[...uom]};
console.log(uomObj);
Which yields this:
Object {
"0": "inches",
"1": "centimeters",
"2": "yards",
"3": "meters",
}
but that does not match the desired result of:
Object {
"inches": "",
"centimeters": "",
"yards": "",
"meters": "",
}
Can this be achieved with an ES6 approach? If so, how?
You can use Array.from with a mapping function to convert each value inside your set into an object and then use Object.assign() with the spread syntax to merge the array of objects into a single resulting object like so:
const uom = new Set(['inches', 'centimeters', 'yards', 'meters']);
const res = Object.assign(...Array.from(uom, v => ({[v]:''})));
console.log(res);
Create an object, then loop over the values in the set and create a property for each one. The reduce method is probably the most compact way to do that.
const uom = new Set(['inches', 'centimeters', 'yards', 'meters']);
const result = Array.from(uom).reduce( (a,c) => { a[c]=""; return a; }, {});
console.log(result);
Here's one way:
[...uom].reduce((o, u) => {
o[u] = '';
return o;
}, {})
You can use Array.prototype.reduce to get the elements from the set and accumulate it in an object:
const uom = new Set(['inches', 'centimeters', 'yards', 'meters']);
const getObjectFromSet = (set) => {
return [...set].reduce((r, k) => {r[k] = ""; return r; },{});
}
console.log(getObjectFromSet(uom));
You can also use the Object.fromEntries for ES6+ code:
const uom = new Set(['inches', 'centimeters', 'yards', 'meters']);
const getObjectFromSet = (set) => {
return Object.fromEntries(Array.from(set, (k) => [k, ""]));
}
console.log(getObjectFromSet(uom));
For anyone like myself who was looking for the reverse of this for something similar to the below
Object {
"length": "inches",
"length": "centimeters",
"length": "yards",
"length": "meters",
}
This code worked for me
const mySet = new Set(['inches', 'centimeters', 'yards', 'meters']);
let newArr = [];
const setToObj = [...mySet].map(el => {
newArr.push({ 'length': el });
});
Related
Suppose there is an array like this:
const a = [ {p:1}, {p:2}, {p:3} ];
Is it possible to destructure this array in order to obtain p = [1, 2, 3] ?
Because this does not work :
const [ ...{ p } ] = a; // no error, same as const p = a.p;
// p = undefined;
Edit
In response to all the answers saying that I need to use Array.prototype.map, I am aware of this. I was simply wondering if there was a way to map during the destructuring process, and the answer is : no, I need to destructure the array itself, then use map as a separate step.
For example:
const data = {
id: 123,
name: 'John',
attributes: [{ id:300, label:'attrA' }, { id:301, label:'attrB' }]
};
function format(data) {
const { id, name, attributes } = data;
const attr = attributes.map(({ label }) => label);
return { id, name, attr };
}
console.log( format(data) };
// { id:123, name:'John', attr:['attrA', 'attrB'] }
I was simply wondering if there was a way, directly during destructuring, without using map (and, respectfully, without the bloated lodash library), to retrive all label properties into an array of strings.
Honestly I think that what you are looking for doesn't exist, normally you would map the array to create a new array using values from properties. In this specific case it would be like this
const p = a.map(element => element.p)
Of course, there are some packages that have many utilities to help, like Lodash's map function with the 'property' iteratee
you can destructure the first item like this :
const [{ p }] = a;
but for getting all values you need to use .map
and the simplest way might be this :
const val = a.map(({p}) => p)
Here's a generalized solution that groups all properties into arrays, letting you destructure any property:
const group = (array) => array.reduce((acc,obj) => {
for(let [key,val] of Object.entries(obj)){
acc[key] ||= [];
acc[key].push(val)
}
return acc
}, {})
const ar = [ {p:1}, {p:2}, {p:3} ];
const {p} = group(ar)
console.log(p)
const ar2 = [{a:2,b:1},{a:5,b:4}, {c:1}]
const {a,b,c} = group(ar2)
console.log(a,b,c)
I have this Object:
{
"data": {
"success": true,
"historical": true,
"date": "2022-01-01",
"base": "MXN",
"rates": {
"COFFEE": 0.02158734144632395,
"CORN": 0.008232645172711363,
"COTTON": 0.04320921676820366,
"SOYBEAN": 0.0036714622235960175,
"SUGAR": 0.25680398615582695,
"WHEAT": 0.00017592643558262669
},
"unit": "per bushel"
}
}
And I want to iterate over "rates" to replace the values of each key with 1 / value
I tried with: (prueba is the Object name)
Object.values(this.prueba.data.rates).forEach((val) => {
console.log(val)
val = 1 / val;
console.log(val)
})
But how to replace those values or how can I saved them in another array or Object
Your code doesn't work because the change you made to val is only reflected within the scope of the callback.
You should instead loop through each property and set its value.
const obj={data:{success:!0,historical:!0,date:"2022-01-01",base:"MXN",rates:{COFFEE:.02158734144632395,CORN:.008232645172711363,COTTON:.04320921676820366,SOYBEAN:.0036714622235960175,SUGAR:.25680398615582695,WHEAT:.00017592643558262669},unit:"per bushel"}};
let r = obj.data.rates;
Object.keys(r).forEach(e => r[e] = 1 / r[e])
console.log(obj)
If you're using Typescript it's necessary to declare the object like so:
const obj: {[key: string]: any} = ...
You can iterate over Object.entries (or Object.keys) and replace the value for each key.
let obj={data:{success:!0,historical:!0,date:"2022-01-01",base:"MXN",rates:{COFFEE:.02158734144632395,CORN:.008232645172711363,COTTON:.04320921676820366,SOYBEAN:.0036714622235960175,SUGAR:.25680398615582695,WHEAT:.00017592643558262669},unit:"per bushel"}};
Object.entries(obj.data.rates).forEach(([k, v]) => obj.data.rates[k] = 1 / v);
console.log(obj);
I think it will be cleaner to write it explicitly using for loops:
let obj = {} //original object stated in question
let obj2 = Object.create(null);//DON'T just use {}, see below
for(let productName in obj.data.rates){
let inverse = 1/obj.data.rates[productName];
//to edit the object directly
obj.data.rates[productName] = inverse;
//to add to another object
obj2[productName] = inverse;
}
The difference between {} and Object.create(null) can be found here
You can combine Object.entries(), Array#forEach() and Destructuring assignment
Code:
const obj = {data:{success:0,historical:0,date:"2022-01-01",base:"MXN",rates:{COFFEE:.02158734144632395,CORN:.008232645172711363,COTTON:.04320921676820366,SOYBEAN:.0036714622235960175,SUGAR:.25680398615582695,WHEAT:.00017592643558262669},unit:"per bushel"}}
const replaceValue = ({ data: { rates: r }}) =>
Object
.entries(r)
.forEach(([k, v]) => r[k] = 1 / v)
replaceValue(obj)
console.log(obj)
I have the following structure:
let mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
and I want to add this piece of data
const issueTypes = ["4000"]
to each of the arrays of the object keys ending with this
mappings = {
"1002": ["1000", "1003", "4000"],
"2000": ["2001", "2002", "4000"]
}
This is what I have so far:
mappings = Object.keys(mappings).reduce((prev, curr, index) => {
console.log("prevous", prev)
console.log("curret", curr)
return ({
...prev, [curr]: //unsure of this part which is kind of crucial
})}, mappings)
Any help would be really appreciated
Why not just iterate over the values of the object, and push?
const mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
const issueTypes = ["4000"]
for (const arr of Object.values(mappings)) {
arr.push(...issueTypes);
}
console.log(mappings);
If it must be done immutably, map the entries of the object to a new array of entries, while spreading the new issueTypes into the value.
const mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
const issueTypes = ["4000"]
const newMappings = Object.fromEntries(
Object.entries(mappings).map(
([key, arr]) => [key, [...arr, ...issueTypes]]
)
);
console.log(newMappings);
The procedure is quite simple. What you need to do is this —
Iterate over each value of the mappings object.
Push the new value
Refer to the following code and adapt —
let mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
const issueTypes = ["4000"]
for (const item in mappings) {
mappings[item].push(issueTypes[0])
}
Hope this helps! :)
I'm working on an existing project that takes query parameters in an oddly formatted string dot notation. But they must be converted into objects before processing. This is currently being performed with conditionals on specific keys by name.
How can this be performed dynamically? Below you will find an example of the input and desired output.
Input:
{
date.gte: '2019-01-01',
date.lt: '2020-01-01'
}
Output:
{
date: {
gte: '2019-01-01',
lt: '2020-01-01'
}
}
You could use reduce and split methods to split each key into array and build nested structure based on that array.
const data = {
'date.gte': '2019-01-01',
'date.lt': '2020-01-01'
}
const result = Object.entries(data).reduce((r, [k, v]) => {
k.split('.').reduce((a, e, i, ar) => {
return a[e] || (a[e] = ar[i + 1] ? {} : v)
}, r)
return r;
}, {})
console.log(result)
By you saying "oddly formatted string dot notation" I assume you mean "date.gte" & "date.lt"
const input = {
"date.gte": "2019-01-01",
"date.lt": "2020-01-01"
};
const res = Object.keys(input).reduce(
(result, current) => {
const [, operator] = current.split(".");
result.date[operator] = input[current];
return result;
},
{ date: {} }
);
console.log(res);
Here's an improvement on Dan's answer that doesn't rely on knowing the key-value pairs in the original object. As much as Nenad's answer blows this out of the water, I worked for too long on this to not post it :)
const formatter = (weirdObject, s = '.') => Object.keys(weirdObject).reduce((acc, cur) => {
const [parent, child] = cur.split(s);
if (!acc[parent]) acc[parent] = {};
acc[parent][child] = weirdObject[cur];
return acc;
}, {});
// -- Demonstration:
const input1 = {
"date.gte": "2019-01-01",
"date.lt": "2020-01-01"
};
const input2 = {
"person:name": "Matt",
"person:age": 19
};
const res1 = formatter(input1);
const res2 = formatter(input2, ':');
console.log(res1);
console.log(res2);
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)));