Converting object to array format with Javascript - javascript

I have a data object like this:
{
"backgroundColor": [
"#E5700F",
"#DA830F",
],
"data": [
26,
10,
],
}
I want to change the format to be like this:
[
{
"backgroundColor": "#E5700F",
"data": 26,},
{
"backgroundColor": "#DA830F",
"data": 10,},
]
how to achieve it using javascript?

You could do this:
const old = {
backgroundColor: ["#E5700F", "#DA830F"],
data: [26, 10],
};
let newArray = [];
old.backgroundColor.forEach((item, idx) => {
newArray.push({ backgroundColor: item, data: old.data[idx] });
});

This could work if the object is not dynamic.
let data = {
"backgroundColor": [
"#E5700F",
"#DA830F",
],
"data": [
26,
10,
],
};
let result = data.backgroundColor.map(function(item, index) {
return {
backgroundColor: item,
data: data.data[index]
}
});
console.log(result);

You can do it like this:
Note that the array's length may not be equal, so it is best to consider this in your data conversion routine.
let sourceData = {
"backgroundColor": [
"#E5700F",
"#DA830F",
],
"data": [
26,
10,
],
};
let result = [];
let length = Math.max(sourceData.backgroundColor.length, sourceData.data.length);
for (let index = 0; index < length; index++) {
result.push({
"backgroundColor": sourceData.backgroundColor[index],
"data": sourceData.data[index]
})
}
console.log(result);

Related

Sum every last index value with previous values in JS

I have an array:
array = {
"data": [
{ "value": [ 100, 13, 16 ] },
{ "value": [ 101, 14, 17 ] },
{ "value": [ 12, 15, 18 ] }
]
}
Which I am reformatting into a new array of just the columns:
const columnArray = jsonData.map( (current, index, arr) => {
let out = [];
for( let i = 0; i < current.value.length; i++ ) {
out.push( arr[ i ].value[ index ] );
}
return out;
});
// output
[
[ 100, 101, 12 ],
[ 13, 14, 15 ],
[ 16, 17, 18 ]
]
How would I re-write the columnArray mapping to do the column array and be able to sum from the previous value?
So the intended output from the original array would be:
[
[ 100, 201, 213 ],
[ 13, 27, 42 ],
[ 16, 33, 51 ]
]
I would also like the summing to be scalable (though it will always be in a 1:1 ratio). So if the data has 20 items, then each value will have 20 integers in that array too.
I have tried looping through but that didn't work as I only sum from the previous, not all the previous. And this wouldn't scale either:
const columnArray = jsonData.map( (current, index, arr) => {
let out = [];
for( let i = 0; i < current.value.length; i++ ) {
// dont touch first
if( i < 1 ) {
out.push( arr[ i ].value[ index ] );
} else {
out.push( arr[ i ].value[ index ] + arr[ i - 1 ].value[ index ] )
}
}
return out;
});
Instead of pushing the array element, add it to a variable accumulating the running totals, and push that.
const jsonData = [{
"value": [100, 13, 16]
},
{
"value": [101, 14, 17]
},
{
"value": [12, 15, 18]
}
];
const columnArray = jsonData.map((current, index, arr) => {
let out = [];
let total = 0;
for (let i = 0; i < current.value.length; i++) {
total += arr[i].value[index]
out.push(total);
}
return out;
});
console.log(columnArray);
or with a nested map():
const jsonData = [{
"value": [100, 13, 16]
},
{
"value": [101, 14, 17]
},
{
"value": [12, 15, 18]
}
];
const columnArray = jsonData.map((current, index, arr) => {
let total = 0;
return arr.map(el => total += el.value[index])
});
console.log(columnArray);
You're thinking this in the wrong way. You're storing the sum in the list, not anywhere else. So even tho your index is increasing, the resulting sum resides in the list, so to achieve your goal you have to save it in some variable then push the variable into the final list. Follow this code below:
const columnArray = array.data.map((current, index, arr) => {
let out = [];
let temp;
for (let i = 0; i < current.value.length; i++) {
// dont touch first
if (i < 1) {
temp = arr[i].value[index];
out.push(arr[i].value[index]);
} else {
temp = arr[i].value[index] + temp;
out.push(temp);
}
}
return out;
});
something like that...
const array0 = {
"data": [
{ "value": [ 100, 13, 16 ] },
{ "value": [ 101, 14, 17 ] },
{ "value": [ 12, 15, 18 ] }
]
}
const
rowCount = array0.data.reduce((c,{value})=>Math.max(c,value.length) ,0)
, arrResult = Array(rowCount).fill(0).map(x=>Array(array0.data.length).fill(0))
;
arrResult.forEach((_,i,arr)=>
{
array0.data[i].value.forEach((v,j)=>
{
arr[j][i] = v + (i? arr[j][i-1] : 0 )
})
})
console.log( arrResult)
.as-console-wrapper {max-height: 100%!important;top:0}

How to get the min, max, and sum of JSON data

I had JSON data that came back with single int values. With some changes, the values are now coming back as arrays of ints (as well as the original format).
{
"value": 10,
"value": 70,
"value": 30,
"value": 200
}
- and -
{
"value": [64, 13, 55, 34, 52, 43, 59, 20, 20],
"value": [10, 90, 20, 80, 30, 70, 60, 40, 50]
}
I had a formula that would return the min, max, and sum of the old version of JSON data. Now it doesn't work, and I can't figure out what would be the best way to re-write the function to handle the arrays. Or if its better to make a second function to handle just arrays and do a check if it is an int or array?
Is there a way that would return (from the numbers above):
// no value array, apply to all
[ 10, 200, 310 ] // min, max, sum
- and -
// for each of the value arrays
[ 23, 64, 360 ] // val 1 - min, max, sum
[ 10, 90, 450 ] // val 2 - min, max, sum
// input data
const value = document.querySelectorAll( "div" ).forEach( el => {
const contents = el.textContent, // get the text in the <div>
json = JSON.parse( contents ), // parse the data
jsonData = json.data; // get the data only
// normalise the data
// #from: https://stackoverflow.com/a/67294607/1086990
const normaliseData = arr => {
const data = arr.map(({ value }) => value);
return typeof arr[0].value === 'number' ? [data] : data;
};
// add into const
const valueArray = normaliseData( jsonData );
// get the min / max / sum
const minMaxSum = valueArray.forEach( e => {
return [
Math.min(...e),
Math.max(...e),
[...e].reduce((v, w) => v + w)
];
});
// output
console.log( minMaxSum );
});
<div>
{ "data": [ { "value": [64, 23, 45, 34, 52, 43, 59, 40] }, { "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ] }
</div>
<div>
{ "data": [ { "value": 600 }, { "value": 70 }, { "value": 30 } ] }
</div>
Normalize the data by testing the type of the value of the first object in each array:
const valueInArray = [{ value: [64, 23] }, { value: [45, 34] }];
const valueAsSingle = [{ value: 600 }, { value: 70 }];
const normalizeData = arr => {
const data = arr.map(({ value }) => value);
return typeof arr[0].value === 'number'
? [data]
: data;
};
console.log(normalizeData(valueInArray));
//=> [ [ 64, 23 ], [ 45, 34 ] ]
console.log(normalizeData(valueAsSingle));
//=> [ [ 600, 70 ] ]
Now they are the same shape, and so you can treat them equally.
You can use Math.max and Math.min to find the maximum and minimum of the array then assign the values in the specific variables.
Currently, when you are using val.value it is consisting of the whole array and hence you also need to iterate over the array to find the max, min, or sum.
To find the sum use reduce on the val.value array and then add it in the acc[2].
// input data
const valueInArray = document.getElementById("valueInArray").innerHTML,
valueAsSingle = document.getElementById("valueAsSingle").innerHTML;
// parse
const jsonArray = JSON.parse( valueInArray ),
jsonNumber = JSON.parse( valueAsSingle ),
jsonArrayData = jsonArray.data,
jsonNumberData = jsonNumber.data;
// get numbers
const minMaxSumArray = jsonArrayData.reduce( ( acc, val ) => {
// smallest number
acc[0] = (
( acc[0] === undefined || Math.min(...val.value) < acc[0] ) ?
Math.min(...val.value) : acc[0]
)
// largest number
acc[1] = (
( acc[1] === undefined || Math.max(...val.value) > acc[1] ) ?
Math.max(...val.value) : acc[1]
)
// sum of numbers
acc[2] = (
acc[2] === undefined ?
val.value.reduce((v, w) => v + w) : val.value.reduce((v, w) => v + w) + acc[2]
)
console.log('answer', acc)
// return the array
return acc;
}, [] );
<div id="valueInArray">
{ "data": [ { "value": [64, 23, 45, 34, 52, 43, 59, 40] }, { "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ] }
</div>
<div id="valueAsSingle">
{ "data": [ { "value": 10 }, { "value": 70 }, { "value": 30 } ] }
</div>
My take on it: first, create a single Array of all values (either arrays or single) by concatening them and using Array.flat() to flatten it. Then use a reducer to determine the sum and use Math.min/max for the min and max values.
// input data
const valuesInArray = JSON.parse(
document.querySelector("#valueInArray").textContent).data;
const singleValues = JSON.parse(
document.querySelector("#valueAsSingle").textContent).data;
// get all values from the objects to a single Array of values
// (so: convert all to single values)
const allValues = valuesInArray.map( v => v.value )
.concat(singleValues.reduce( (acc, val) => [...acc, +val.value], [] ) )
.flat();
// let's see what we have
console.log(`All values from both objects: ${JSON.stringify(allValues)}`);
// create sum, min and max
const [ sum, min, max, ] = [
allValues.reduce( (a, v) => a + +v, 0),
Math.min(...allValues),
Math.max(...allValues) ];
console.log(`From all values sum is ${sum}, min ${min} and max ${max}`);
div {
display: none;
}
<div id="valueInArray">
{ "data": [
{ "value": [64, 23, 45, 34, 52, 43, 59, 40] },
{ "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ]
}
</div>
<div id="valueAsSingle">
{ "data":
[ { "value": 10 }, { "value": 70 }, { "value": 30 } ]
}
</div>
The second snippet aggregates data per value, where the single values are added as a values array to valuesInArray.
// input data
const valuesInArray = JSON.parse(
document.querySelector("#valueInArray").textContent).data;
const singleValues = JSON.parse(
document.querySelector("#valueAsSingle").textContent).data;
// create sum, min and max *per value*, in one go
const aggregatesAdded = valuesInArray
.concat({ value: singleValues.reduce( (acc, val) => [...acc, +val.value], [] ) } )
.reduce( (acc, val) => [...acc, {...val, aggregatedValues: {
sum: val.value.reduce( (a, v) => a + +v, 0 ),
min: Math.min(...val.value),
max: Math.max(...val.value) } }
], [])
document.querySelector("pre").textContent =
JSON.stringify({data: aggregatesAdded}, null, 2);
div {
display: none;
}
<div id="valueInArray">
{ "data": [
{ "value": [64, 23, 45, 34, 52, 43, 59, 40] },
{ "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ]
}
</div>
<div id="valueAsSingle">
{ "data":
[ { "value": 10 }, { "value": 70 }, { "value": 30 } ]
}
</div>
<pre id="result"></pre>

Adding values to an object whilst iterating over data

I have a set of JSON - that i need to iterate over as I essentially need to create a string which contains certain identifiers in it. At the moment I am mapping over the data and then over stimulus list. ( I have the index which from the event as I only need data from that index).
The problem I have is the cell_id is always the same . And I need to create a string.
const key = `cell_Id${cell_id}:step_Id${item.step_id}:study_id${studyId}:stim_id${item.stimulus_id}`
I suspect I need to add things to an object as I am interating over the data - what is the best way to do this?
thanks
Here is the JSON
{
"study_id": 16,
"data": [
{
"cell_id": 23,
"stimulus_list": [
{
"stimulus_id": 96,
"step_id": 62
}
]
},
{
"cell_id": 24,
"stimulus_list": [
{
"stimulus_id": 95,
"step_id": 61
}
]
}
]
}
data
.map(item => item.stimulus_list)
.map(item => item[index]);
You can have a nested map over the data and then flatten the result using reduce.
const obj = {
"study_id": 16,
"data": [
{
"cell_id": 23,
"stimulus_list": [
{
"stimulus_id": 96,
"step_id": 62
}
]
},
{
"cell_id": 24,
"stimulus_list": [
{
"stimulus_id": 95,
"step_id": 61
}
]
}
]
}
const res = obj.data
.map(item => {
return [].concat(item.stimulus_list.map(stimulus => `cell_Id${item.cell_id}:step_Id${stimulus.step_id}:study_id${obj.study_id}:stim_id${stimulus.stimulus_id}`))
}).reduce((acc, item) => {
acc = acc.concat(item)
return acc;
}, [])
console.log(res)

Filter array of objects by array of ids

I have an array activeIds of ids of services and there is another array servicesList which contains objects of services.
Example: -
activeIds = [202, 204]
serviceList = [{
"id":201,
"title":"a"
},
{
"id":202,
"title":"a"
},
{
"id":203,
"title":"c"
},
{
"id":204,
"title":"d"
},
{
"id":205,
"title":"e"
}];
I want all the services(obj) whose ids are not a part of the first array i.e., activeIds. From the above example code I want service obj of ids 201,203,205
Final output -
expectedArray = [{
"id":201,
"title":"a"
},
{
"id":203,
"title":"c"
},
{
"id":205,
"title":"e"
}];
Here is my attempt to code. But it is not correct at all. Please help-
const activeIds = e; // [202, 204]
const obj = [];
this.serviceList.map((s: IService) => {
activeIds.map((id: number) => {
if (id !== s.id) {
obj.push(s);
}
});
});
You can simply use array.filter with indexOf to check the matching element in the next array.
var arr = serviceList.filter(item => activeIds.indexOf(item.id) === -1);
DEMO
let activeIds = [202, 204]
let serviceList = [{
"id":201,
"title":"a"
},
{
"id":202,
"title":"a"
},
{
"id":203,
"title":"c"
},
{
"id":204,
"title":"d"
},
{
"id":205,
"title":"e"
}];
let arr = serviceList.filter(function(item){
return activeIds.indexOf(item.id) === -1;
});
console.log(arr);
You can do this with filter and includes methods.
const activeIds = [202, 204]
const serviceList = [{"id":201,"title":"a"},{"id":202,"title":"a"},{"id":203,"title":"c"},{"id":204,"title":"d"},{"id":205,"title":"e"}]
const result = serviceList.filter(({id}) => !activeIds.includes(id));
console.log(result)
Use filter & indexOf method.indexOf will check if the current id is present in activeIds array
var activeIds = [202, 204]
var serviceList = [{
"id": 201,
"title": "a"
},
{
"id": 202,
"title": "a"
},
{
"id": 203,
"title": "c"
},
{
"id": 204,
"title": "d"
},
{
"id": 205,
"title": "e"
}
];
var filteredArray = serviceList.filter(function(item) {
return activeIds.indexOf(item.id) === -1
});
console.log(filteredArray)
you can combine indexOf to check if the current id is on the active array and filter the array.

2-dimensional array to object (JavaScript)

I have an array, that holds a large number of two-dimensional arrays:
var myArray = [
[2260146,2334221,"copy"],
[1226218,2334231,"copy"],
[2230932,-1,"copy"],
[2230933,-1,"copy"],
[2230934,-1,"copy"]
]
I need to convert this array into an object of the following form to send it as JSON:
var json = [
{
"s_id": 2260146,
"t_id": 2334221,
"type": "copy"
},
{
"s_id": 1226218,
"t_id": 2334231,
"type": "copy"
},
{
"s_id": 12,
"t_id": -1,
"type": "copy"
}
]
("s_id" should be myArray[0][0], "t_id myArray[0][1], and "type" myArray[0][2] and so on.)
How can I get the array in the desired form? Thanks in advance.
json = myArray.map(function(x) {
return {
"s_id": x[0],
"t_id": x[1],
"type": x[2]
}
})
Be aware that map is not supported in IEs < 9.
You could destructure the parameter in map and use Shorthand property names:
const myArray=[[2260146,2334221,"copy"],[1226218,2334231,"copy"],[2230932,-1,"copy"],[2230933,-1,"copy"],[2230934,-1,"copy"]]
const output = myArray.map(([s_id, t_id, type]) => ({ s_id, t_id, type }))
console.log(output)
Try with:
var length = myArray.length,
json = [];
for ( var i = 0; i < length; i++ ) {
var subArray = myArray[i],
item = {
s_id: subArray[0],
t_id: subArray[1],
type: subArray[2]
};
json.push(item);
}
How to traverse through the following structure from 2D array
weekearn,monthearn is variable containing array of objects.
I need loop because I don't know the number of products
const stackdata = {
datasets:[{
data: weekearn,
label: 'Product 1',
backgroundColor: 'rgb(255, 87, 51)',
borderColor: 'rgb(255, 99, 132)',
},
{
data: monthearn,
label: 'Product 2',
backgroundColor: 'rgb(155, 87, 51)',
borderColor: 'rgb(255, 99, 32)',
}
]
};

Categories