Learning JavaScript. I need to plot some data (I'm using Nivo).
I have data from my API in the format of:
[{"as_at_date":"2020-02-21","value":815202269.5,"num":139},{"as_at_date":"2020-02-25","value":809209302.32,"num":139},{"as_at_date":"2020-03-12","value":723686212.35,"num":139},{"as_at_date":"2020-03-13","value":734798809.24,"num":139},{"as_at_date":"2020-03-16","value":701366943.2,"num":139},{"as_at_date":"2020-03-17","value":710833514.89,"num":139},{"as_at_date":"2020-03-18","value":699154469.83,"num":139},{"as_at_date":"2020-03-19","value":694649684.34,"num":139},{"as_at_date":"2020-03-20","value":685400033.9,"num":139}]
To plot a line chart with Nivo I need to alter the above array into:
[{"id": 'XXXXX",
"data": [{"x":"2020-02-21","y":815202269.5},{"x":"2020-02-25","y":809209302.32},{"x":"2020-03-12","y":723686212.35},{"x":"2020-03-13","y":734798809.24},{"x":"2020-03-16","y":701366943.2},{"x":"2020-03-17","y":710833514.89},{"x":"2020-03-18","y":699154469.83},{"x":"2020-03-19","y":694649684.34},{"x":"2020-03-20","y":685400033.9}]
Ignore "num" property.
nest the data and create an "id"
Change as_at_date to "x", value to "y"
Last attempt was trying to use .map like .map(item => [{"x": item['as_at_date']}, {"y": item['value']}]) but wasn't quite right.
Appreciate any help, thanks!
I would use .reduce() to create the nested data first. Then adding id and data properties to the final object.
Try the following:
const data = [{"as_at_date":"2020-02-21","value":815202269.5,"num":139},{"as_at_date":"2020-02-25","value":809209302.32,"num":139},{"as_at_date":"2020-03-12","value":723686212.35,"num":139},{"as_at_date":"2020-03-13","value":734798809.24,"num":139},{"as_at_date":"2020-03-16","value":701366943.2,"num":139},{"as_at_date":"2020-03-17","value":710833514.89,"num":139},{"as_at_date":"2020-03-18","value":699154469.83,"num":139},{"as_at_date":"2020-03-19","value":694649684.34,"num":139},{"as_at_date":"2020-03-20","value":685400033.9,"num":139}];
const nested = data.reduce((a, c) => a.concat({x: c['as_at_date'], y: c['value']}), []);
const result = {
id: 'XXXXX',
data: nested
};
console.log(result);
I hope this helps!
map is certainly the way to go.
Here's my approach:
const data = [{"as_at_date":"2020-02-21","value":815202269.5,"num":139},{"as_at_date":"2020-02-25","value":809209302.32,"num":139},{"as_at_date":"2020-03-12","value":723686212.35,"num":139},{"as_at_date":"2020-03-13","value":734798809.24,"num":139},{"as_at_date":"2020-03-16","value":701366943.2,"num":139},{"as_at_date":"2020-03-17","value":710833514.89,"num":139},{"as_at_date":"2020-03-18","value":699154469.83,"num":139},{"as_at_date":"2020-03-19","value":694649684.34,"num":139},{"as_at_date":"2020-03-20","value":685400033.9,"num":139}];
function reformattedData(arr) {
// Destructure only the required properties
return arr.map(({ as_at_date, value }) => {
// And just return those values in a new object
// using the new property names
return { x: as_at_date, y: value };
});
}
const out = { id: 'xxx', data: reformattedData(data) };
console.log(out);
Your attempt was almost correct, just omit the surrounding []:
const input = [{"as_at_date":"2020-02-21","value":815202269.5,"num":139},{"as_at_date":"2020-02-25","value":809209302.32,"num":139},{"as_at_date":"2020-03-12","value":723686212.35,"num":139},{"as_at_date":"2020-03-13","value":734798809.24,"num":139},{"as_at_date":"2020-03-16","value":701366943.2,"num":139},{"as_at_date":"2020-03-17","value":710833514.89,"num":139},{"as_at_date":"2020-03-18","value":699154469.83,"num":139},{"as_at_date":"2020-03-19","value":694649684.34,"num":139},{"as_at_date":"2020-03-20","value":685400033.9,"num":139}];
const outputData = input.map(item => ({ x: item.as_at_date, y: item.value }));
console.log(outputData);
const result = {
id: 'XXXX', // create your id here,
data: outputData,
};
console.log(result);
You can try this one
const array = [{"as_at_date":"2020-02-21","value":815202269.5,"num":139},{"as_at_date":"2020-02-25","value":809209302.32,"num":139},{"as_at_date":"2020-03-12","value":723686212.35,"num":139},{"as_at_date":"2020-03-13","value":734798809.24,"num":139},{"as_at_date":"2020-03-16","value":701366943.2,"num":139},{"as_at_date":"2020-03-17","value":710833514.89,"num":139},{"as_at_date":"2020-03-18","value":699154469.83,"num":139},{"as_at_date":"2020-03-19","value":694649684.34,"num":139},{"as_at_date":"2020-03-20","value":685400033.9,"num":139}];
const formatted_array = input.map((item) => {
return {x: item.as_at_date, y: item.value}});
const final_data = {
id: 'XXXX',
data: formatted_array ,
};
console.log(final_data);
i want to know if i can set the same value for multiple keys in the following:
React functional component state:
const [state, setState] = useState(
key1: 'same-value',
key2: 'same-value',
key3: 'same-value'
);
React class component state:
state = {
key1: 'same-value',
key2: 'same-value',
key3: 'same-value'
};
Javascript object:
const state = {
key1: 'same-value',
key2: 'same-value',
key3: 'same-value'
};
I want to know if something like this is possible:
const state = {
state1, state2, state3: 'same-value';
};
I want to know if something like this is possible
Not in an object literal, no. You can do it after creating the object:
const state = {};
state.key1 = state.key2 = state.key3 = 'same-value';
Or you could make key2 and key3 accessor properties for key1, meaning they'd track its value (change key1, and you see the change in key2 and key3), because although using them looks like a simple property access, in fact it's a function call.
const state = {
key1: 'some-value',
get key2() { return this.key1; },
get key3() { return this.key1; }
};
console.log(state.key1); // 'some-value'
console.log(state.key2); // 'some-value'
console.log(state.key3); // 'some-value'
I'm not suggesting that, just noting it's possible.
I have object which I want to validate.
// valid object because all values of keys are present in details object
var object = {
details: {
key1: 'stringValue1',
key2: 'stringValue2',
key3: 'stringValue3'
},
keys: ['key1', 'key2', 'key3']
}
// invalid object as key5 is not present in details
var object = {
details: {
key4: 'stringValue4'
},
keys: ['key4', 'key5']
}
// invalid object as key5 is not present and key8 should not exist in details
var object = {
details: {
key4: 'stringValue4',
key8: 'stringValue8',
},
keys: ['key4', 'key5']
}
All the keys present in keys should be present in details also.
I tried this using Joi.ref()
var schema = Joi.object({
details: Joi.object().keys(Object.assign({}, ...Object.entries({...Joi.ref('keys')}).map(([a,b]) => ({ [b]: Joi.string() })))),
keys: Joi.array()
})
But this is not working because Joi.ref('keys') will get resolved at validation time.
How can I validate this object using Joi?
Using object.pattern and array.length
var schema = Joi.object({
details: Joi.object().pattern(Joi.in('keys'), Joi.string()),
keys: Joi.array().length(Joi.ref('details', {
adjust: (value) => Object.keys(value).length
}))
});
stackblitz
You can validate the array(if you want) then make a dynamic schema and validate that.
const arrSchema = Joi.object({
keys: Joi.array()
});
then,
const newSchema = Joi.object({
details: Joi.object().keys(data.keys.reduce((p, k) => {
p[k] = Joi.string().required();
return p;
},{})),
keys: Joi.array()
})
This should probably do it.
You have to set allowUnknown: true in validate() option.
I have a trivial issue where I have two simple objects like this
var state = {
Value1: "Something",
Value2: "Else"
};
var claims = [
"Viewing",
"Editing",
"Delete"
];
and I would like to create an object that looks like this.
var newState = {
Value1: "Something",
Value2: "Else",
/* Array merged into properties with defaults. */
Viewing: true,
Editing: true,
Delete: true
};
I considered using jQuery $.map() and alternatively Object.assign() (which seems to be closer to what I want) but I cant seem to work out exactly how to achieve the result I need.
So as the heading states, how do I merge an array into an existing object as properties while also setting default values?
For the simple given example try the following:
var state = {Value1:"Something",Value2:"Else"};
claims = ["Viewing","Editing","Delete"];
let res = Object.assign(state, claims.reduce((a,c) => {a[c] = true; return a},{}))
console.log(res)
You can add a property using variable name with obj[myStringAsName] = value
var state = {
Value1: "Something",
Value2: "Else"
};
var claims = [
"Viewing",
"Editing",
"Delete"
];
var newState = state;
claims.forEach(function(item){
newState[item] = true;
})
console.log(newState)
I converted the array to object using reduce and merged both objects
var state = {
Value1: "Something",
Value2: "Else"
};
var claims = [
"Viewing",
"Editing",
"Delete"
];
var obj = claims.reduce(function(acc, cur) {
acc[cur] = true;
return acc;
}, {});
var returnedData = Object.assign(state, obj);
console.log(returnedData)
You could use destructuring and a simple Array#forEach
const state = {
Value1: "Something",
Value2: "Else"
};
const claims = [
"Viewing",
"Editing",
"Delete"
];
const newState = {
...state
}
claims.forEach(prop => newState[prop] = true);
console.log(newState)
I have several objects and i would like to get one and check a specific property
so i have
data: [{is_guest: true},{permission:'is_allowed_ip'}]
Now when i check the console.log(route.data) am getting
0:{is_guest:true},
1:{permission:'is_allowed_ip' }
and typeof route.data is an object
now i would like to get the object with is_guest:true
So i have tried
const data = Object.keys(route.data).map((index) => {
if (route.data[index].is_guest) {
return route.data[index]
}
});
console.log("route data is",data) //this still returns all the items
But the above fails returning all the objects.
How do i loop through all the objects and retrieve just only one with the is_guest key and value true
Sounds like you want Object.values, not Object.keys, and filter:
const data = Object.values(route.data).filter(e => e.is_guest);
Object.values is fairly new, but present on up-to-date Node, and entirely polyfillable.
Example:
const route = {
data: [
{is_guest: true},
{permission:'is_allowed_ip'}
]
};
const data = Object.values(route.data).filter(e => e.is_guest);
console.log(data);
Using E6:
data.filter(o => o.is_guest)
You can use the filter method.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
I added some ids into your array just to make easier to understand.
// added ids to exemplify
const data = [
{id: 1, is_guest: true},
{id: 2, permission:'is_allowed_ip'},
{id: 3, is_guest: true},
{id: 4, is_guest: false},
]
// filter results
const filtered = data.filter(item => item.is_guest)
// just to show the result
document.querySelector('.debug').innerHTML = JSON.stringify(filtered, null, 2);
<pre><code class="debug"></code></pre>