Flatten and merge array of array of objects in Javascript - javascript

Here is my input:
var toto=[
[
{ "a": "24" },
{ "a": "23.9"},
{ "a": "NaN"},
{ "a": "3" }
],
[
{"b": "19"},
{"b": "20"},
{"b": "NaN"},
{"b": "3" }
],
[
{"c": "27"},
{"c": "28"},
{"c": "NaN"},
{"c": "3" }
]
];
All arrays of objects are guaranteed to contain the same number of objects.
I would like to obtain in output:
var out = [
{ "a": "24", "b": "19", "c":"27" },
{ "a": "23.9", "b": "20", "c":"28"},
{ "a": "NaN", "b": "NaN", "c":"NaN"},
{ "a": "3", "b": "3", "c": "3"}
]
Which is, for each inner array, take the Nth element and merge it into an object, and push it into a result array.
I have a "braindead" solution which is iterating on the first sub-array and then iterating on the other arrays:
var out = [];
$(toto[0]).each(function(i, item) {
var o = {};
$(toto).each(function( j, array) {
var item = array[i];
o[Object.keys(item)[0]] = Object.values(item)[0];
});
out.push(o);
});
It works, but it is kind of hideous, and I would like to know if there's a solution using functional methods like map and reduce.
Do you guys know?

You could use Array#reduce, Array#forEach and Object.assign for a pivot of the data with the same index for the inner array.
var toto=[[{ a: "24" }, { a: "23.9" }, { a: "NaN" }, { a: "3" }], [{ b: "19" }, { b: "20" }, { b: "NaN" }, { b: "3" }], [{ c: "27" }, { c: "28" }, { c: "NaN" }, { c: "3" }]],
result = toto.reduce(function (r, a) {
a.forEach(function (b, i) {
r[i] = r[i] || {};
Object.assign(r[i], b);
});
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

javascript cannot map array of objects with nested values

Trying to map array of objects with values nested in child objects structure like:
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
},...]
to the structure like:
[
{ name: 'B', value: 1 },
{ name: 'D', value: '45' },
{ name: 'E', value: '234' },
{ name: 'A', value: '543' },
{ name: 'C', value: '250' }
]
and the result of the mapping is undefined
const mapped = objs.map((key, index) => {
Object.keys(key).map(el => ({
name: el
}))
})
Example: Stackblitz
You are missing return statement and value property definition.
Besides you may want to use flatMap instead of map in order to avoid a nested array in the result:
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
}]
const mapped = objs.flatMap((key, index) => {
return Object.keys(key).map(el => ({
name: el,
value: key[el].value
}))
})
console.log(mapped)
You should operate on objs[0], not objs, because it is an array of one object, not array of objects.
let array = []
for(let object in objs[0]){
array.push({
"name": object,
"value": objs[0][object].value
})
}
return is missing in Object.keys. As well instead of Object.keys use Object.entries to get key and value.
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
}];
const mapped = objs.map((key, _) => {
return Object.entries((key)).map(([name, {
value
}]) => ({
name,
value
}))
}).flat();
console.log(mapped);

Iterate through nested JSON object array and store as key-value pair

I have to iterate through this JSON:
{
"data": 321563,
"group": [
{
"added": 42421,
"normal": {
"x": 39,
"y": "0.1300",
"b": "0.4326",
"c": "0.0552",
"f": 166833
},
"j": "240313",
"b": "0.2251",
"a": "dda",
"b": "0.101",
"a": 922,
"f": {
"c": 39,
"d": "0.263",
"a": "2.8955",
"h": "0.3211",
"d": 274
},
"a": false,
"k": 5,
"w": "0.072",
"d": "0.045",
"e": 3
},
I only want the j and k stored like a key value pair e.g. "j":k
I need to loop all of it, and store it to a file.
You can use a map to get a new array of items, this will not affect the old array.
const data = {
"game_count": 8750,
"sets": [
{
"appid": "221540",
"true_count": 9,
"bgs_avg": "0.10",
// Other data here
},
{
"appid": "123456",
"true_count": 9,
"bgs_avg": "0.20",
// Other data here
}
]
}
// Use "data.sets = data.sets.map(...)" to replace the data
// The following will only assign to a new variable
const newArray = data.sets.map(itm => { return {appid: itm.appid, true_count: itm.true_count} })
console.log(newArray)
We can also take the data and assign it directly back to the original overwriting it just by using data.sets = data.sets.map(...) as seen here:
const data = {
"game_count": 8750,
"sets": [
{
"appid": "221540",
"true_count": 9,
"bgs_avg": "0.10",
// Other data here
},
{
"appid": "123456",
"true_count": 9,
"bgs_avg": "0.20",
// Other data here
}
]
}
data.sets = data.sets.map(itm => { return {appid: itm.appid, true_count: itm.true_count} })
console.log(data)
In simple javascript this should work -
let newObj = {}
for(let i=0; i<obj.group.length; i++){
newObj[obj.group[i].j] = obj.group[i].k
}
Where 'obj' is your object
newObj will be you new Object which will contain all the key value pair

converting object properties which are array like to array is not working

I have an nested object like following(it can have any depth):
{
"a": 5,
"b": {
"0": 1,
"1": "x"
},
"x": {
"a": 1,
"1": "z"
},
"c": {
"0": 3,
"1": "Am",
"3":{
"0": 3,
"1": "x",
"2":{
"0": 3,
"1": "Y"
},
"length": 3
},
"length": 4
}
}
I have to convert it as following(object may or may not have length property):
{
"a": 5,
"x": {
"a": 1,
"1": "z"
},
"b": [1,"x"],
"c": [3, "Am",undefind, [ 3, "x", [ 3, "Y" ] ] ]
}
I written method like following:
function formatObjToArr(obj) {
var kys = Object.keys(obj);
var isObj = (/[^0-9]/g).test(kys.join('')) && !Array.isArray(obj);
if(!isObj){
obj.length===undefined && (obj.length = Math.max.apply(null,kys.map(function (i) { return parseInt(i) }))+1);
obj = Array.prototype.map.apply(obj,[function (i) { return i}]);
obj.forEach(function (i) {
(typeof i === "object" && i!==null) && formetObjToArr(i);
})
}else {
for (var property in obj) {
if (obj.hasOwnProperty(property) && property!=='length') {
if (typeof obj[property] === "object" && obj[property]!==null) {
formetObjToArr(obj[property]);
}
}
}
}
}
But it just adds the length property it is not changing the type. output of my code is as follows:
{
"a": 5,
"b": {
"0": 1,
"1": "x",
"length": 2
},
"x": {
"a": 1,
"1": "z"
},
"c": {
"0": 3,
"1": "Am",
"3": {
"0": 3,
"1": "x",
"2": {
"0": 3,
"1": "Y",
"length": 2
},
"length": 3
},
"length": 4
}
}
You could take a check for object and check if the keys are in the wanted range for an index or length, then create an array of it. This array should be converted, too.
function convert(object) {
var keys;
if (!object || typeof object !== 'object') {
return object;
}
keys = Object.keys(object);
if (keys.every(k => k === 'length' || Math.floor(k) === +k && k >= 0 && k < Math.pow(2, 31))) {
return Object.assign([], object).map(convert);
}
return Object.assign(...keys.map(k => ({ [k]: convert(object[k]) })));
}
var data = { a: 5, b: { 0: 1, 1: "x" }, x: { 1: "z", a: 1 }, c: { 0: 3, 1: "Am", "3": { 0: 3, 1: "x", 2: { 0: 3, 1: "Y" }, length: 3 }, length: 4 } };
console.log(convert(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
var data = {
"a": 5,
"b": {
"0": 1,
"1": "x"
},
"c": {
"0": 3,
"1": "Am",
"length": 2
}
}
for(const d in data){
if(typeof data[d] === 'object'){
delete data[d]['length'];
data[d] = Object.values(data[d]);
}
}
console.log(data);

Angular 6 merge two array to count the length of key

I have an array of two objects which has another array of objects, i want the count of all objects of property "value" in the following sample.
var data = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
];
I have used the following logic :-
let _data = data.RESULT;
console.log(JSON.stringify(_data));
_data.forEach(element => {
this.someObj = element;
});
The expected result should be the length of values property, i.e. 4
If you want to find only length of "values" array then you need to do this
data = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
]
length = 0;
constructor() {
this.data.forEach((d) => {
length = length + d.values.length;
});
console.log('length', length);
}
https://stackblitz.com/edit/angular-3daqcy?file=src%2Fapp%2Fapp.component.ts
Created a function that adds the lengths of the values array
var arr = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
]
function getKeysLength(arr){
var count = 0;
arr.forEach((val)=>{count= count+ val.values.length})
return count
}
var ans = getKeysLength(arr);
console.log("ans",ans);
If you want to do it in a single line then you can do it with map and reduce,map creates a new array with the elements as the length of the values property and reduce calculates the sum of the new array elements . Which gives you the sum of the length of all values property arrays.
Here is the code below -
let data = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
];
let totalLength = data.map(x => x.values.length).reduce((a,b) => a+b,0);
console.log(temparr);
Here is a working Stackblitz with Angular 6
https://stackblitz.com/edit/hello-angular-6-ewa5tb?file=src/app/app.component.ts

How to make a JSON object out of a dictionary?

I'me new to JavaScript. In the browser I receive a long dictionary like this:
{"cat": "4" , "dog": "5", "fish": "9" }
I'm wondering what is the most efficient way to convert it to a JSON object like:
[
{
"name": "cat",
"value": "4"
},
{
"name": "dog",
"value": "5"
},
{
"name": "fish",
"value": "9"
}
]
You can Loop through it and push each key-value-pair to an Array.
var tValue = {"cat": "4" , "dog": "5", "fish": "9" };
var tList = [];
for(var tKey in tValue) tList.push({name: tKey, value: tValue[tKey]});
console.log(tList);
You can just loop over the dictionary object keys using Object.keys() method, and use .map() method to transform each iterated key/value pair to the appropriate object:
var results = Object.keys(obj).map(function(k) {
return {
name: k,
value: obj[k]
};
});
Demo:
var obj = {
"cat": "4",
"dog": "5",
"fish": "9"
};
var results = Object.keys(obj).map(function(k) {
return {
name: k,
value: obj[k]
};
});
console.log(results);
You can use the function Object.entries to get every key-value pairs and with the function map build the desired output.
let obj = {"cat": "4" , "dog": "5", "fish": "9" },
result = Object.entries(obj).map(([name, value]) => ({name, value}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this by this way :
Call a for in loop and read your first object
Push the name and the value in your new object one by one..
Sample code :
var a = {"cat": "4" , "dog": "5", "fish": "9" };
var newJSON = [] ;
console.log(a);
for ( key in a ) {
newJSON.push({name : key, value : a[key]});
}
console.log(newJSON);
You can have this kind of formatted object
{
animals : [
{"name":"cat", "value": 4},
{"name":"dog", "value": 5},
{"name":"fish", "value": 9}
]
}
or like this
[
{"name":"cat", "value": 4},
{"name":"dog", "value": 5},
{"name":"fish", "value": 9}
]

Categories