How to change array to object in Javascript? - javascript

I have list of objects
[
{ regionName:'Alabama',code:'AL', value: 89 },
{ regionName:'Alaska',code:'AK', value: 112 },
{ regionName:'Arizona',code:'AZ', value: 101 },
{ regionName:'Arkansas',code:'AR', value: 123 }
]
which I want to convert to below format -
{
AL: { value: 89 },
AK: { value: 112 },
AZ: { value: 101 },
AR: { value: 123 }
}
How this can be achieved in JS?

You can use map method by passing a callback provided function as parameter which is applied for every item from the given array.
let array=[ { regionName:'Alabama',code:'AL', value: 89 }, { regionName:'Alaska',code:'AK', value: 112 }, { regionName:'Arizona',code:'AZ', value: 101 }, { regionName:'Arkansas',code:'AR', value: 123 } ];
array = Object.assign(...array.map(({ code, value }) => ({ [code]: {value:value }})));
console.log(array);

You can use array.prototype.reduce so on every iteration you append new key (AL, AK or AZ) into the final result.
const arr = [
{ regionName:'Alabama',code:'AL', value: 89 },
{ regionName:'Alaska',code:'AK', value: 112 },
{ regionName:'Arizona',code:'AZ', value: 101 },
{ regionName:'Arkansas',code:'AR', value: 123 }
]
const result = arr.reduce((prev, curr) => {
return {
...prev,
[curr.code]: { value: curr.value },
}
}, {})
console.log(result)

May be I am late but this should also work with simple Array.prototype.map()
var array_of_objects = [
{ regionName:'Alabama',code:'AL', value: 89 },
{ regionName:'Alaska',code:'AK', value: 112 },
{ regionName:'Arizona',code:'AZ', value: 101 },
{ regionName:'Arkansas',code:'AR', value: 123 }
];
var required = {};
var result = array_of_objects.map(function(obj){
return (required[obj.code] = {value:obj.value});
})
console.log(required);
Result:
{
"AL": {"value": 89},
"AK": {"value": 112},
"AZ": {"value": 101},
"AR": {"value": 123}
}

Related

ReactJS Convert json to [name: value:] pair

I have this json object.
[
{
"crime": "LARCENY-NON_VEHICLE",
"count": "23217"
},
{
"crime": "AUTO_THEFT",
"count": "13675"
},
{
"crime": "LARCENY-FROM_VEHICLE",
"count": "28627"
},
{
"crime": "BURGLARY-RESIDENCE",
"count": "16312"
}
]
I need to display this data in a pie chart so I need to convert it to this format.
[
{name: "LARCENY-NON_VEHICLE", value: 23217},
{name: "AUTO_THEFT", value: 13675},
{name: "LARCENY-FROM_VEHICLE", value: 28627},
{name: "BURGLARY-RESIDENCE", value: 16312}
]
This is how Im retrieving the data using axios.
You can just use map to return a new array with values from old array
const data = [{
"crime": "LARCENY-NON_VEHICLE",
"count": "23217"
},
{
"crime": "AUTO_THEFT",
"count": "13675"
},
{
"crime": "LARCENY-FROM_VEHICLE",
"count": "28627"
},
{
"crime": "BURGLARY-RESIDENCE",
"count": "16312"
}
];
const newData = data.map(item => {
return {
name: item.crime,
value: +item.count // + to convert string to number
}
});
console.log(newData)
You can simply format an array by calling map function
const arr = [
{
crime: "LARCENY-NON_VEHICLE",
count: "23217",
},
{
crime: "AUTO_THEFT",
count: "13675",
},
{
crime: "LARCENY-FROM_VEHICLE",
count: "28627",
},
{
crime: "BURGLARY-RESIDENCE",
count: "16312",
},
];
arr.map((e) => ({
name: e.crime,
count: Number.parseInt(e.count)
}))

How to transform an object into an array of objects by its keys?

I've got a data source:
const data = {
A: [{
value: 1
}, {
value: 2
}, {
value: 38
}],
B: [{
value: 46
}, {
value: 23
}, {
value: 32
}],
C: [{
value: 2345
}, {
value: 56
}, {
value: 3
}]
}
I need to transform this object in an array of objects like below:
[{
A: 1,
B: 46,
C: 2345
}, {
A: 2,
B: 23,
C: 56
}, {
A: 38,
B: 32,
C: 3
}]
I made some attempts but still not there:
a)
const result = Object.keys(data).map(key => data[key])
b)
const b = Object.keys(data).reduce((acc, curr, i) => {
const values = data[curr].map(el => el.value)
acc[curr] = values[i]
return acc
}, [])
EDIT:
All arrays (A, B, C) should have the same length. In case it doesn't, value should be "-" for the missing ones
eg:
[{
A: 1,
B: 46,
C: 2345
}, {
A: 2,
B: 23,
C: 56
}, {
A: 38,
B: 32,
C: -
}]
Assuming the number of objects in your value arrays is the same (or less than) the number of properties in your data object, you could map your data keys to new objects that you can create using Object.fromEntries(). You can pass an array of mapped values to this fromEntries call, which goes through all your keys a, b, c and uses the current index from the outer loop to determine which object to grab its value from:
const data = { A: [{ value: 1 }, { value: 2 }, { value: 38 }], B: [{ value: 46 }, { value: 23 }, { value: 32 }], C: [{ value: 2345 }, { value: 56 }, { value: 3 }] };
const res = Object.keys(data).map((_, i, arr) =>
Object.fromEntries(arr.map(key => [key, data[key][i]?.value ?? "-"]))
);
console.log(res);
If you need a more robust approach, I suggest you go with a solution such as T.J. Crowder's that can handle the case where there are more objects in your arrays than there are properties in your object.
I'm going to assume that the fact there are three properties (A, B, and C) and the fact there are three values for each of them is a coincidence and that we can't rely on that.
If so, see comments:
// Get the keys
const keys = Object.keys(data);
// A blank object to use as a template for a new array entry w/blank values
const blankEntry = Object.fromEntries(keys.map(key => [key, "-"]));
// Create the result array; since we don't know how long it'll need to
// be without reading through the array, just start with a blank one)
const result = [];
// Loop through the properties
for (const key of keys) {
// Loop through this property's values
const values = data[key];
for (let index = 0; index < values.length; ++index) {
// Get the object at this index, creating it if not there
let entry = result[index];
if (!entry) {
// Make a shallow copy of the template to create the entry
result[index] = entry = {...blankEntry};
}
// Set this key's value
entry[key] = values[index].value;
}
}
Live Example (I've added a fourth entry to A to show that the three and three thing isn't important to the solution, and to show the "-" thing working):
const data = {
A: [{
value: 1
}, {
value: 2
}, {
value: 38
}, {
value: 42
}],
B: [{
value: 46
}, {
value: 23
}, {
value: 32
}],
C: [{
value: 2345
}, {
value: 56
}, {
value: 3
}]
};
const keys = Object.keys(data);
const blankEntry = Object.fromEntries(keys.map(key => [key, "-"]));
const result = [];
for (const key of keys) {
const values = data[key];
for (let index = 0; index < values.length; ++index) {
let entry = result[index];
if (!entry) {
result[index] = entry = {...blankEntry};
}
entry[key] = values[index].value;
}
}
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}
You could get the max length first and then map the values.
const
data = { A: [{ value: 1 }, { value: 2 }, { value: 38 }, { value: 99 }], B: [{ value: 46 }, { value: 23 }, { value: 32 }], C: [{ value: 2345 }, { value: 56 }, { value: 3 }] },
entries = Object.entries(data),
length = entries.reduce((r, [, { length }]) => Math.max(r, length), 0),
result = entries.reduce(
(r, [k, a]) => r.map((o, i) => ({ ...o, ...(i in a && { [k]: a[i].value }) })),
Array.from(
{ length },
() => Object.fromEntries(entries.map(([k]) => [k, '-']))
)
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can create an empty object with - and assign value after with reduce() and forEach().
const data = { A: [ { value: 1, }, { value: 2, }, { value: 38, }, ], B: [ { value: 46, }, { value: 23, }, { value: 32, }, ], C: [ { value: 2345, }, { value: 56, }, { value: 3, }, ], };
const keys = Object.keys(data);
const emptyObj = keys.map(_ =>
keys.reduce((o, key) => ({ ...o, [key]: "-" }), {})
);
const o = keys.reduce((a, b) => {
data[b].forEach((el, i) => {
a[i][b] = el.value;
});
return a;
}, emptyObj);
console.log(o);
I think I'd try with something like:
// input
const data = {
A: [{ value: 1 }, { value: 2 }, { value: 38 }, { value: 57 }],
B: [{ value: 46 }, { value: 23 }, { value: 32 }, { value: 42 }],
C: [{ value: 2345 }, { value: 56 }, { value: 3 }],
D: [{ value: 345 }, { value: 684 }]
};
// I am using an IIFE to initialize `output` in order not to pollute the global scope
// with variables that are not re-used anywhere else but obviously it is not strictly necessary.
const output = (() => {
const keys = Object.keys(data);
const maxItemsNr = Math.max(...Object.values(data).map(item => item.length));
const newArr = [];
for (let i = 0; i < maxItemsNr; i++) {
const item = keys.reduce((outObj, key) => {
outObj[key] = data[key][i] ? data[key][i].value : '-';
return outObj;
}, {});
newArr.push(item);
}
return newArr
})();
// test
console.log(output);
And this is my take on it:
const data = { A: [{value: 1}, {value: 2}],
B: [{value: 46}, {value: 23}, {value: 32}, {value: 38}, {value: 42}],
C: [{value: 2345}, {value: 56}, {value: 3}] };
const ntrs = Object.entries(data),
blnk = ntrs.reduce((a,[key])=>(a[key]="-",a),{}),
rslt = [];
ntrs.forEach(([k,arr])=> arr.forEach(({value},i)=>(rslt[i]=rslt[i]||{...blnk})[k]=value) )
console.log(rslt);
.as-console-wrapper {
max-height: 100% !important;
}
My solution. But I think Nick Parson's solution is better.
const data = {A: [{value: 1}, {value: 2}, {value: 38}],B: [{value: 46}, {value: 23}, {value: 32}],C: [{value: 2345}, {value: 56}, {value: 3}]}
function transform(object) {
const res = [];
Object.keys(object).forEach((key)=> {
object[key].forEach(({value},i) => {
if(res[i]) {
res[i][key] = value
} else {
res[i] = {
[key]: value
}
}
})
})
return res
}
console.log(transform(data))

Pushing data from this array to another uses the least loop

I want to config data from 'data2' array to 'dataConvert' array
and I want to find another way of optimizing.
let dataConvert = [];
data2 = [
{
time: "2020-7",
tasks: [
{
key: "p1",
value: 15
},
{
key: "p2",
value: 13
},
]
},
{
time: "2020-8",
tasks: [
{
key: "p1",
value: 16
},
{
key: "p2",
value: 19
},
]
},
{
time: "2020-9",
tasks: [
{
key: "p1",
value: 12
},
{
key: "p2",
value: 93
},
]
}
]
After adding data to the 'dataConvert' array, then 'dataConvert' is formatted as follows:
dataConvert = [
["x","2020-7", "2020-8", "2020-9"],
["p1", 15, 16, 12],
["p2", 13, 19, 93]
]
i tried use reduce , I want to find another way of optimizing.
let dateConvert = [], valueConvert = [];
data2.forEach(x=>{
let date = new Date(x.time);
if (date) {
let getYear = date.getFullYear();
let getMonth = date.getMonth() + 1;
let newDate = `${getYear}-${getMonth}-1`;
return dateConvert = [...dateConvert, newDate];
}
})
dateConvert.unshift("x");
// get p1 p2 value
let allTasks = data2.flatMap(x => x.tasks);
valueConvert = Object.values(allTasks.reduce((arr, item) => {
arr[item.key] = arr[item.key] || [item.key];
arr[item.key].push(item.value);
return arr;
}, {}));
dataConvert = [...[dateConvert], ...valueConvert];
thank u.
You could take nested loops and store the index in an object for faster access of key.
const
data = [{ time: "2020-7", tasks: [{ key: "p1", value: 15 }, { key: "p2", value: 13 }] }, { time: "2020-8", tasks: [{ key: "p1", value: 16 }, { key: "p2", value: 19 }] }, { time: "2020-9", tasks: [{ key: "p1", value: 12 }, { key: "p2",value: 93 }] }],
dataConvert = [['x']],
indices = {};
data.forEach(o => {
dataConvert[0].push(o.time);
o.tasks.forEach(({ key, value }) => {
if (!(key in indices)) indices[key] = dataConvert.push([key]) - 1;
dataConvert[indices[key]].push(value);
});
});
console.log(dataConvert);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sort function not working: sort an object by value

<p id="demo">
depending on what you clicked I will appear or hide.
</p>
<script>
var items = [
{ name: "Edward", value: 21 },
{ name: "Sharpe", value: 37 },
{ name: "And", value: 45 },
{ name: "The", value: -12 },
{ name: "Magnetic", value: 13 },
{ name: "Zeros", value: 37 }
];
//sort the object by value
items.sort(function(a, b) {
return a.value - b.value;
});
for (var i = 0; i < items.length; i++) {
document.getElementById("demo").innerHTML =
items[i].name + items[i].value;
}
</script>
The output is And45, but the result I want is to display the object by value.
Any advice is appreciated!Thank you in advance
Get rid of the for-loop and just use a map and join to transform the items into a string representation if that's what you're asking:
var items = [
{ name: "Edward", value: 21 },
{ name: "Sharpe", value: 37 },
{ name: "And", value: 45 },
{ name: "The", value: -12 },
{ name: "Magnetic", value: 13 },
{ name: "Zeros", value: 37 }
];
//sort the object by value
items.sort(function(a, b) {
return a.value - b.value;
});
document.getElementById("demo").innerHTML = items.map(o => `${o.name}: ${o.value}`).join('<br>');
<p id="demo">
depending on what you clicked I will appear or hide.
</p>
There's nothing wrong with your sort, you're just re-assigning the html several times, ending with the last value in the sorted array.

Setting array keys dynamically based on length

Given an array in this format:
[
[{
name: "name",
value: "My-name"
},
{
name: "qty",
value: "1"
},
{
name: "url",
value: "test.com"
},
{
name: "comment",
value: "my-comment"
}
],
[{
name: "name",
value: "My-name2"
},
{
name: "qty",
value: "3"
},
{
name: "url",
value: "test2.com"
}
],
[{
name: "name",
value: "My-name3"
},
{
name: "qty",
value: "1"
},
{
name: "url",
value: "test3.com"
},
{
name: "comment",
value: "my-comment3"
}
]
]
I'm looking to switch that to:
[
[
{ name: "My-name" },
{ qty: "1" },
{ url: "test.com" },
{ comment: "my-comment", }
],[
{ name: "My-name2" },
{ qty: "3" },
{ url: "test2.com",
],[
{ name: "My-name3", },
{ qty: "1", },
{ url: "test3.com", },
{ comment: "my-comment3", }
]
]
In other words, swapping out the array keys but maintaining the object structure within each array element.
I've tried looping over each element and can swap the keys out using something like:
newArray[iCount][item.name] = item.value;
However I'm then struggling to preserve the object order. Note that the comment field may or may not appear in the object.
With Array.map() function:
var arr = [
[{name:"name",value:"My-name"},{name:"qty",value:"1"},{name:"url",value:"test.com"},{name:"comment",value:"my-comment"}],
[{name:"name",value:"My-name2"},{name:"qty",value:"3"},{name:"url",value:"test2.com"}],
[{name:"name",value:"My-name3"},{name:"qty",value:"1"},{name:"url",value:"test3.com"},{name:"comment",value:"my-comment3"}]
],
result = arr.map(function(a){
return a.map(function(obj){
var o = {};
o[obj.name] = obj.value
return o;
});
});
console.log(result);
Check my moreBetterOutput value. I think will be better.
If you still need a result like your example in the question then you can check output value.
const input = [
[
{
name:"name",
value:"My-name"
},
{
name:"qty",
value:"1"
},
{
name:"url",
value:"test.com"
},
{
name:"comment",
value:"my-comment"
}
],
[
{
name:"name",
value:"My-name2"
},
{
name:"qty",
value:"3"
},
{
name:"url",
value:"test2.com"
}
],
[
{
name:"name",
value:"My-name3"
},
{
name:"qty",
value:"1"
},
{
name:"url",
value:"test3.com"
},
{
name:"comment",
value:"my-comment3"
}
]
]
const output = input.map(arr => arr.map(obj => ({[obj.name]: obj.value})))
const moreBetterOutput = output.map(arr => arr.reduce((acc, item, index) => {
acc[Object.keys(item)[0]] = item[Object.keys(item)[0]];
return acc;
}, {}) )
//console.log(output);
console.log(moreBetterOutput);
Another map function:
const result = array.map( subarray =>
Object.assign(...subarray.map( ({name, value}) => ({ [name] : value }) ))
);

Categories

Resources