My Object contains different datatypes including array. I want to concatenate all arrays(in a single array)
I have written using foreach and concat.
Is there any way I can have a better solution, or this is correct?
See the below snippet. concat array value3 and value5 into single array.
var Input = {
"value1": 10,
"value2": "abcd",
"value3": [
{
"v1": 100,
"v2": 89
},
{
"v1": 454,
"v2": 100
}
],
"value4": "xyz",
"value5": [
{
"v6": 1,
"v7": -8
},
{
"v1": 890,
"v2": 10
}
]
}
var OutputData = [];
let keys = Object.keys(Input);
keys.forEach(key => {
if (Array.isArray(Input[key])) {
try {
OutputData= OutputData.concat(Input[key])
} catch (error) {
}
}
});
console.log(OutputData)
You could use Array.prototype.filter() with Array.prototype.flat() method get a cleaner code. First get all the values using Object.values() method. Then use filter method to get the arrays and at last use flat method to get a new array with all sub-array elements concatenated.
const input = {
value1: 10,
value2: 'abcd',
value3: [
{
v1: 100,
v2: 89,
},
{
v1: 454,
v2: 100,
},
],
value4: 'xyz',
value5: [
{
v6: 1,
v7: -8,
},
{
v1: 890,
v2: 10,
},
],
};
const ret = Object.values(input)
.filter((x) => Array.isArray(x))
.flat();
console.log(ret);
I think this might be a little bit cleaner to read:
var input = {
"value1": 10,
"value2": "abcd",
"value3": [{
"v1": 100,
"v2": 89
},
{
"v1": 454,
"v2": 100
}
],
"value4": "xyz",
"value5": [{
"v6": 1,
"v7": -8
},
{
"v1": 890,
"v2": 10
}
]
};
let res = [];
for (let k in input) {
if (input.hasOwnProperty(k) && Array.isArray(input[k]))
input[k].forEach(x => res.push(x));
}
console.log(res);
Related
I have a data structure as follows:
UPDATED: to have more than one object in innerValues
const data = {
"dates": [
"2015-09-09T00:00:00",
"2015-09-09T00:10:00",
"2015-09-09T00:20:00",
],
"innerValues": [
{
"name": "Name_1",
"value": [
104,
105,
107,
]
},
{
"name": "Name_2",
"value": [
656,
777,
145,
]
}],
}
I would like to create an output like:
const outPut = [
["2015-09-09T00:00:00", 'Name_1', 104 ],
["2015-09-09T00:10:00", 'Name_1', 105 ],
["2015-09-09T00:20:00", 'Name_1', 107 ],
["2015-09-09T00:00:00", 'Name_2', 104 ],
["2015-09-09T00:10:00", 'Name_2', 105 ],
["2015-09-09T00:20:00", 'Name_2', 107 ]
]
So far I have this, I know I could do this with forEach etc also - but as an example.
const m = data.dates;
let arr = [];
for (var i = 0; i < m.length; i++) {
arr[i] = new Array(m[i]);
}
console.log(arr);
This gives:
0: ['2021-09-09T00:00:00']
1: ['2021-09-09T00:10:00']
2: ['2021-09-09T00:20:00']
Which is where I want to start, however if I map over inner.values and try to create an new array from that, it does not return three separate arrays but one.e.g
const newArray = x.forEach(inner => console.log(new Array(inner)))
Output
0: (3) [104, 105, 107]
How could I achieve the above desired structure.
You can use reduce and map to loop over innerValues and their values
const dates = data.dates
const newArr = data.innerValues.reduce((acc, cur, i) => {
acc.push(cur.value.map((value, i) => ([dates[i], cur.name, value])));
return acc;
}, []).flat()
console.log(newArr)
<script>
const data = {
"dates": [
"2015-09-09T00:00:00",
"2015-09-09T00:10:00",
"2015-09-09T00:20:00",
],
"innerValues": [{
"name": "Name_1",
"value": [
104,
105,
107,
]
},
{
"name": "Name_2",
"value": [
656,
777,
145,
]
}
],
}
</script>
I have an array of objects of the structure coming from server response of iterated array object like as sample
var arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 },
......n
];
var arrObj2 = [
{"id":"1","value3":21, "value14":13},
{"id":"2","value3":21, "value4":13 },
......n
];
var arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 },
......n
];
But now I want to append the array values inot single new array according to key following structure of as iterated values of above array Expected Output:
var finalObj = [
{
"id" : 1
"value" : 21,
"value1" : 13,
"value3" : 21,
"value4" : 13,
"value5" : 21,
"value6" : 13,
},
{
"id" : 2
"value" : 21,
"value1" : 13,
"value3" : 21,
"value4" : 13,
"value5" : 21,
"value6" : 13,
},
.....n
];
You can use reduce for concated arrays
const arrObj1 = [
{ id: '1', value: 21, value1: 13 },
{ id: '2', value: 21, value1: 13 },
];
const arrObj2 = [
{ id: '1', value3: 21, value14: 13 },
{ id: '2', value3: 21, value4: 13 },
];
const arrObj3 = [
{ id: '1', value5: 21, value6: 13 },
{ id: '2', value5: 21, value6: 13 },
];
const result = [...arrObj1, ...arrObj2, ...arrObj3].reduce(
(acc, { id, ...rest }) => ({ ...acc, [id]: acc[id] ? { ...acc[id], ...rest } : { ...rest } }),
{},
);
console.log(Object.entries(result).map(([id, data]) => ({ id, ...data })));
Push you arrays to a new array (you have to have your sub arrays in other list to loop through them) and then use flat, after that group your object according to the id property
var arrObj1 = [{
"id": "1",
"value": 21,
"value1": 13
},
{
"id": "2",
"value": 21,
"value1": 13
},
];
var arrObj2 = [{
"id": "1",
"value3": 21,
"value14": 13
},
{
"id": "2",
"value3": 21,
"value4": 13
},
];
var arrObj3 = [{
"id": "1",
"value5": 21,
"value6": 13
},
{
"id": "2",
"value5": 21,
"value6": 13
},
];
const input = [];
input.push(arrObj2, arrObj3);
const preResult = input.flat();
result = preResult.reduce((acc, x) => {
const index = acc.findIndex(y => y.id === x.id)
if (index >= 0) {
acc[index] = {
...acc[index],
...x
}
} else {
acc.push(x)
}
return acc;
}, arrObj1)
console.log(result)
You can iterate over array-length and push here for every entry 1 entry to the result. For getting this entry take a new object with the id and iterate over all (3 or perhaps more) arrays. For every array take the i-th entry and push for every key an entry with key:value (except for the key id itself).
Remark: You can use as much arrays you want and every object could contain as much value-prperties as you need. The only restriction is that every array has the same count of objects.
var arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 }
];
var arrObj2 = [
{"id":"1","value3":21, "value4":13},
{"id":"2","value3":21, "value4":13 }
];
var arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 }
];
let result =[];
let arrayAll = [arrObj1, arrObj2, arrObj3];
for (let i=0; i<arrayAll[0].length; i++) {
let obj = arrayAll[0][i];
let res = { id: obj.id};
for (let j=0; j<arrayAll.length; j++) {
let obj = arrayAll[j][i];
Object.keys(obj).forEach(key => {
if (key!='id') res[key] = obj[key];
})
}
result.push(res);
}
console.log(result);
Since you are using id to merge multiple objects, Map is one of the good option to merge.
let arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 },
];
let arrObj2 = [
{"id":"1","value3":21, "value14":13},
{"id":"2","value3":21, "value4":13 },
];
let arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 },
];
let mergedArray = [...arrObj1,...arrObj2,...arrObj3].reduce((acc,curr) =>{
if(acc.has(curr.id)){
acc.set(curr.id, {...acc.get(curr.id),...curr});
}else{
acc.set(curr.id,curr);
}
return acc;
},new Map())
console.log(Array.from(mergedArray,x=>x[1]));
I want to restructure the current JSON of data as shown below
const data = [
{
"status": "Complete",
"totalToday": 3,
"weekly": 20
},
{
"status": "Pending",
"totalToday": 5,
"weekly": 13
},
{
"status": "Rejected",
"totalToday": 2,
"weekly": 5
}
];
Expected output:
const newData = [
['Status', 'Total Today', 'Weekly'],
['Complete', 3, 20],
['Pending', 5, 13],
['Rejected', 2, 5]
];
You can use Array.forEach()
const data = [{
"status": "Complete",
"totalToday": 3,
"weekly": 20
},
{
"status": "Pending",
"totalToday": 5,
"weekly": 13
},
{
"status": "Rejected",
"totalToday": 2,
"weekly": 5
}
];
let transformedData = []
transformedData.push(Object.keys(data[0]).map(key => {
return key.replace(/([A-Z])/g, ' $1')
.replace(/^./, (str) => str.toUpperCase())
}))
data.forEach(val => transformedData.push(Object.values(val)))
console.log(transformedData)
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
You can simply use a reduce method, in which you iterate over an Array of Object. On the 0 index, you can use Object.keys() to get the key and Object.values for the corresponding values and push it to the accumulator. For else you can iterate Object values and push it to the accumulator acc.
const data = [
{
"status": "Complete",
"totalToday": 3,
"weekly": 20
},
{
"status": "Pending",
"totalToday": 5,
"weekly": 13
},
{
"status": "Rejected",
"totalToday": 2,
"weekly": 5
}
];
const newData = data.reduce((acc, x, idx) => {
if(idx === 0) {
acc.push(Object.keys(x), Object.values(x));
} else {
acc.push(Object.values(x));
}
return acc;
}, [])
console.log(newData);
Having an array like this:
const data = [
{
"name": "Dave",
"coins": 14,
"weapons": 2,
"otherItems": 3,
"color": "red"
},
{
"name": "Vanessa",
"coins": 18,
"weapons": 1,
"otherItems": 5,
"color": "blue"
},
{
"name": "Sharon",
"coins": 9,
"weapons": 5,
"otherItems": 1,
"color": "pink"
},
{
"name": "Walter",
"coins": 9,
"weapons": 2,
"otherItems": 4,
"color": "white"
}
]
How to count sum of coins, weapons and otherItems using ES6 features? (I'm not attached to this: any simple method would be good.)
data.reduce((first, last) => first + last) generates a chain of [object Object][object Object]s...
You have to process every field separately (note that when you don't specify second parameter for reduce it will take first array object as seed and start processing from the second one):
const data = [
{
"name": "Dave",
"coins": 14,
"weapons": 2,
"otherItems": 3,
"color": "red"
},
{
"name": "Vanessa",
"coins": 18,
"weapons": 1,
"otherItems": 5,
"color": "blue"
},
{
"name": "Sharon",
"coins": 9,
"weapons": 5,
"otherItems": 1,
"color": "pink"
},
{
"name": "Walter",
"coins": 9,
"weapons": 2,
"otherItems": 4,
"color": "white"
}
]
let result = data.reduce((a,c)=> ({
coins: a.coins + c.coins,
weapons: a.weapons + c.weapons,
otherItems: a.otherItems + c.otherItems })
)
console.log(result);
You could take an array of wanted keys for the sums and create an object for the sums and add the wanted values.
const
data = [{ name: "Dave", coins: 14, weapons: 2, otherItems: 3, color: "red" }, { name: "Vanessa", coins: 18, weapons: 1, otherItems: 5, color: "blue" }, { name: "Sharon", coins: 9, weapons: 5, otherItems: 1, color: "pink" }, { name: "Walter", coins: 9, weapons: 2, otherItems: 4, color: "white" }],
keys = ['coins', 'weapons', 'otherItems'],
sums = data.reduce(
(r, o) => (keys.forEach(k => r[k] += o[k]), r),
Object.fromEntries(keys.map(k => [k, 0]))
);
console.log(sums);
You can use Array.prototype.reduce for this.
To make it a little bit more flexible and dynamic, make a Set of keys you want to get a count of.
Then go through each key in the Set and if that key is in the obj, sum it up in an accumulator object in the reduce callback:
const data = [{"name":"Dave","coins":14,"weapons":2,"otherItems":3,"color":"red"},{"name":"Vanessa","coins":18,"weapons":1,"otherItems":5,"color":"blue"},{"name":"Sharon","coins":9,"weapons":5,"otherItems":1,"color":"pink"},{"name":"Walter","coins":9,"weapons":2,"otherItems":4,"color":"white"}]
//Keys to count
const keys = new Set(["coins", "weapons", "otherItems"]);
const count = data.reduce((acc, obj) => {
const objKeys = keys.forEach(key => {
if (obj.hasOwnProperty(key)) {
acc[key] = (acc[key] || 0) + obj[key];
}
});
return acc;
}, {});
console.log(count);
Your idea is right, you need to use reduce method. The problem is that you're summing two objects, not their properties. All you need to do is change the code to the following (to sum the coins):
data.reduce((first, last) => first.coins + last.coins, 0)
And following for weapons:
data.reduce((first, last) => first.weapons + last.weapons, 0)
With this array:
var booksStudents = [
{
name: "David",
books: {
"fantasy": 23,
"action": 31,
"thriller" 21,
}
},
name: "Paul",
books: {
"fantasy": 17,
"action": 13,
"thriller" 23,
}
},
name: "Zoe",
books: {
"fantasy": 5,
"action": 7,
"thriller" 28,
}
}];
I would like to return an array of objects, each containing the name of a person and the sum of all their respective books.
I know how to use the reduce method on a simple array but I am stuck with this array of object.
I was thinking of using .map and .reduce but I did not find something interesting.
booksStudents = booksStudents.map(function(item){
var count = 0;
for(var key in item.books){
count+=item.books[key];
}
item.count = count;
return item;
})
use map and for..in to count the number.
Firstly there are few mistakes in your array of objects, Let me point them.
var booksStudents = [
{
name: "David",
books: {
"fantasy": 23,
"action": 31,
"thriller": 21, // : missing
}
},
{ // { missing
name: "Paul",
books: {
"fantasy": 17,
"action": 13,
"thriller": 23, // : missing
}
},
{ // { missing
name: "Zoe",
books: {
"fantasy": 5,
"action": 7,
"thriller": 28, // : missing
}
}];
So now after this is fixed the solution to get your end result is by using this code.
var newArray = [];
$.each(booksStudents,function(index,value){
var currObj = {};
currObj.name= this.name;
currObj.totalBooks = parseInt(this.books.fantasy) +parseInt(this.books.action)+parseInt(this.books.thriller) ;
newArray.push(currObj);
});
console.log(newArray);
Here is a Wroking Fiddle check console for output
The output is as below .