Related
I've got some headers and peopleData:
const headers = ["name", "age", "nationality"]
const peopleData = [
["John", 31, "Spanish"],
["Jane", 41, "Italian"],
["Johnson", 11, "Thai"],
["Rob", 13, "Japanese"],
]
I want to combine both and return an array of objects looking like:
[{
name: "John",
age: 31,
nationality: "Spanish"
}, {
name: "Jane",
age: 41,
nationality: "Italian"
}, {
name: "Johnson",
age: 11,
nationalityL: "Thai"
}, {
name: "Rob",
age: 13,
nationality: "Japanese"
}]
So far I came up to this:
const people = peopleData.map((person, i) => {
return headers.map((header, index) => {
return {
[header]: person[index]
}
})
})
This solution does not work since it creates nested objects:
[[{
name: "John"
}, {
age: 31
}, {
nationality: "Spanish"
}], [{
name: "Jane"
}, {
age: 41
}, {
nationality: "Italian"
}], [{
name: "Johnson"
}, {
age: 11
}, {
nationality: "Thai"
}], [{
name: "Rob"
}, {
age: 13
}, {
nationality: "Japanese"
}]]
Example below:
Credit to Andreas comment, better performant below
const headers = ["name", "age", "nationality"];
const peopleData = [
["John", 31, "Spanish"],
["Jane", 41, "Italian"],
["Johnson", 11, "Thai"],
["Rob", 13, "Japanese"],
];
const o = peopleData.map(a =>
a.reduce((acc, b, i) => {
acc[headers[i]] = b;
return acc;
}, {})
);
console.log(o);
In one line-er, but less performent
const headers = ["name", "age", "nationality"];
const peopleData = [
["John", 31, "Spanish"],
["Jane", 41, "Italian"],
["Johnson", 11, "Thai"],
["Rob", 13, "Japanese"],
];
const o = peopleData.map(a =>
a.reduce((acc, b, i) => ({ ...acc, [headers[i]]: b }), {})
);
console.log(o);
You can wrap your inner .map() in a call to Object.fromEntries() which will build an object for you - it takes an array of [[key, value],...] pairs, and so you can change your inner map to return a [key, value] pair array instead of objects like so:
const headers = ["name", "age", "nationality"];
const peopleData = [ ["John", 31, "Spanish"], ["Jane", 41, "Italian"], ["Johnson", 11, "Thai"], ["Rob", 13, "Japanese"], ];
const res = peopleData.map(person => Object.fromEntries(person.map(
(val, i) => [headers[i], val]
)));
console.log(res);
Or, you can stick with your approach of returning an array of objects, but then merge the objects within the array together using Object.assign() and the spread syntax ...:
const headers = ["name", "age", "nationality"];
const peopleData = [ ["John", 31, "Spanish"], ["Jane", 41, "Italian"], ["Johnson", 11, "Thai"], ["Rob", 13, "Japanese"], ];
const res = peopleData.map(person => Object.assign(...person.map(
(val, i) => ({[headers[i]]: val})
)));
console.log(res);
A simply solution easy to understand! Iterate all peopleData and put them in a new object using the array headers:
const headers = ["name", "age", "nationality"];
const peopleData = [["John", 31, "Spanish"],["Jane", 41, "Italian"],["Johnson", 11, "Thai"],["Rob", 13, "Japanese"]];
let result = [];
peopleData.forEach((e, i) => { //iterate data
result[i] = {};
result[i][headers[0]] = e[0];
result[i][headers[1]] = e[1];
result[i][headers[2]] = e[2];
});
console.log(result);
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]));
array1 = [{
"id": 1,
"name": "aaa",
},
{
"id": 2,
"name": "bbb"
},
{
"id": 5,
"name": "ccc"
},
{
"id": 6,
"name": "ddd"
},
{
"id": 8,
"name": "eee"
},
{
"id": 12,
"name": "fff"
}]
array2 = [ 5, 6, 8 ,12]
Resulting Array = [ {name: "ccc"}, {name: "ddd"} , {name: "eee"}, {name: "fff"} ]
I am looking to map both arrays to get matching id numbers and get copy the names in the resulting arrray but I didn't succeed. Can you please suggest me how to do it?
Thank you
You could try the following. Basically, you're filtering the first array based on whether or not the id exists in the 2nd array and then mapping it back by only selecting the key(s) you want.
var resultArray = array1.filter(function(arr) {
return array2.indexOf(arr.id) !== -1;
}).map(function(item) {
return {
name: item.name
};
});
Let's turn array1 into an object first, that maps ids to the corresponding objects:
var idMap = {}
array1.forEach(function(element) {
idMap[element.id] = element
})
You can then get the result you want by doing
var result = array2.map(function(id) {
return idMap[id]
});
Try This:
array1 = [{"id": 1,"name": "aaa"},{"id": 2,"name": "bbb"},{"id": 5,"name": "ccc"},{"id": 6,"name": "ddd"},{"id": 8,"name": "eee"},{"id": 12,"name": "fff"}] ;
array2 = [ 5, 6, 8 ,12];
var result = array1.filter(item => array2.includes(item.id)).map(({id,name}) => ({name}));
console.log( result );
I'm running into a weird glitch. I have a bit of code where I'm running thru an array of arrays, grabbing a bunch of city names and concatenating them all together. I need to remove the duplicates from the finished list. This should be pretty simple. Use a count to figure out which city has more than one instance and then splice them out. My returned array isn't coming out right though and I'm not sure why. Can anyone spot what I'm doing wrong?
const input = [
{
name: "ACH2000",
year: 2005,
cities: ['Chicago', 'New York', 'Ames', 'Columbus'],
ages: [12, 32, 2, 51]
},
{
name: "FXG3000",
year: 2008,
cities: ['Chicago', 'Joliet', 'Plymouth', 'Dallas'],
ages: [12, 32, 2, 51]
},
{
name: "GTG1234",
year: 2012,
cities: ['Indy', 'Tampa', 'Houston', 'Dallas'],
ages: [12, 32, 2, 51]
}
];
function getUniqueCities(data){
let citiesInArray = data.map(function(item){ return item.cities });
let concatCities = [].concat.apply([], citiesInArray);
let count = {};
for(let i = 0; i< concatCities.length; i++) {
let num = concatCities[i];
count[num] = count[num] ? count[num]+1 : 1;
if(count[num] > 1){
console.log('bad',num);
concatCities.splice(num, 1);
} else {
console.log('good',num);
}
}
console.log(count);
console.log(concatCities);
}
getUniqueCities(input);
you can try something like this
var input = [
{
name: "ACH2000",
year: 2005,
cities: ['Chicago', 'New York', 'Ames', 'Columbus'],
ages: [12, 32, 2, 51]
},
{
name: "FXG3000",
year: 2008,
cities: ['Chicago', 'Joliet', 'Plymouth', 'Dallas'],
ages: [12, 32, 2, 51]
},
{
name: "GTG1234",
year: 2012,
cities: ['Indy', 'Tampa', 'Houston', 'Dallas'],
ages: [12, 32, 2, 51]
}
];
var citiesStats = {};
input.forEach(data =>
data.cities.forEach(city => {
if (!citiesStats[city]) {
citiesStats[city] = 0;
}
++citiesStats[city];
})
);
var cities = Object.keys(citiesStats);
// ["Chicago", "New York", "Ames", "Columbus", "Joliet", "Plymouth", "Dallas", "Indy", "Tampa", "Houston"]
console.log(cities);
// {"Chicago":2,"New York":1,"Ames":1,"Columbus":1,"Joliet":1,"Plymouth":1,"Dallas":2,"Indy":1,"Tampa":1,"Houston":1}
console.log(citiesStats);
As nnnnnn suggested splicing inside the loop is messing up the indices in the array.
If you can use Set, here is a solution:
Array.from(new Set(concatCities))
Here is a link to fiddle.
I need help with recursively transform json object into another json object.
My input object looks like this:
var my_obj = {
"id": 22,
"eventTypeId": 37,
"eventTypeName": "CommonOnly",
"parentEvent": {
"id": 21,
"eventTypeId": 35,
"eventTypeName": "FullTest",
"parentEvent": {
"id": 20,
"parentEvent": null,
"eventTypeId": 38,
"eventTypeName": "FullTest"
}
},
"childrenEvents": [
{
"id": 24,
"parentEventId": 22,
"eventTypeId": 36,
"eventTypeName": "BlindedTest",
"childrenEvents": []
},
{
"id": 23,
"parentEventId": 22,
"eventTypeId": 38,
"eventTypeName": "OneCustom",
"childrenEvents": []
}
]
}
The output I want is:
var my_obj = {
"id": 20,
"eventTypeId": 38,
"parentEvent": null,
"eventTypeName": "FullTest",
"childrenEvents": [{
"id": 21,
"eventTypeId": 35,
"eventTypeName": "FullTest",
"childrenEvents": [
{
"id": 22,
"eventTypeId": 37,
"eventTypeName": "CommonOnly",
"childrenEvents": [
{
"id": 24,
"parentEventId": 22,
"eventTypeId": 36,
"eventTypeName": "BlindedTest",
"childrenEvents": []
}, {
"id": 23,
"parentEventId": 22,
"eventTypeId": 38,
"eventTypeName": "OneCustom",
"childrenEvents": []
}
]
}
]
}]
}
So I want to be able to get an object where the second parentEvent with parentEvent = null has became a root element, with an array childrenEvents, inside children array will be first parent event object with its own childrenEvents array and inside of this array I want to put existing root object with its own childrenEvents array
I appreciate if somebody could help me to resolve it. Thanks in advance.
My attempt
function rebuild(input)
{
var childrenEvents = [] ;
for ( f in input.parentEvent ) // we may have attributes other than "age"
if (f.parentEvent == null) {
f.parentEvent.push(childrenEvents);
}
else {
f.parentEvent.push(input.parentEvent[f]);
}
if (input.childrenEvents.length !== 0)
{
input.parentEvent[f].push(input.childrenEvents)
}
return input;
}
console.log(rebuild( $scope.myObj))
});
plunker
You could use an object to build all dependencies and take only the one with
parentEvent === null
as tree.
var my_obj = { "id": 22, "eventTypeId": 37, "eventTypeName": "CommonOnly", "parentEvent": { "id": 21, "eventTypeId": 35, "eventTypeName": "FullTest", "parentEvent": { "id": 20, "parentEvent": null, "eventTypeId": 38, "eventTypeName": "FullTest" } }, "childrenEvents": [{ "id": 24, "parentEventId": 22, "eventTypeId": 36, "eventTypeName": "BlindedTest", "childrenEvents": [] }, { "id": 23, "parentEventId": 22, "eventTypeId": 38, "eventTypeName": "OneCustom", "childrenEvents": [] }] },
tree = function (data, root) {
function iter(a) {
var parent;
if (a.childrenEvents && Array.isArray(a.childrenEvents)) {
a.childrenEvents.forEach(iter);
}
a.childrenEvents = o[a.id] && o[a.id].childrenEvents;
o[a.id] = a;
if (a.parentEvent === root) {
r = a;
} else {
if (a.parentEvent && 'id' in a.parentEvent) {
parent = a.parentEvent.id;
}
if ('parentEventId' in a) {
parent = a.parentEventId;
}
if (parent !== undefined) {
o[parent] = o[parent] || {};
o[parent].childrenEvents = o[parent].childrenEvents || [];
o[parent].childrenEvents.push(a);
}
}
if (a.parentEvent) {
iter(a.parentEvent);
delete a.parentEvent;
}
}
var r, o = {};
iter(data);
return r;
}(my_obj, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The title of your question says "recursively" but there is no recursion (that I can see) in your code. Yo need to call rebuild() from within rebuild()... recursively.
Maybe something closer to this (haven't run it)...
function rebuild(input) {
var rslt = input; // If it stays this way, we've reached the end of the line
var parent = inpt.parentEvent;
if (parent) {
parent.childrenEvents = [];
parent.childrenEvents.push(input);
inpt.parentEventId = parent.id;
rslt = rebuild(parent);
}
return rslt;
}