Related
Made example arrays -
const arr = [
{
name: "q",
age: 10,
size: "M",
},
{
name: "w",
age: 10,
size: "S",
},
{
name: "e",
age: 10,
size: "M",
},
];
const arr2 = [
{
name: "q",
age: 10,
size: "M",
},
{
name: "w",
age: 10,
size: "S",
},
{
name: "i",
age: 10,
size: "S",
},
{
name: "x",
age: 10,
size: "S",
},
];
I want to compare the first array (arr) to the second one (arr2) by specific properties in the example case name and size.
If it's a match then I want to store the results in a new array and if it's unmatched then I want to store the results in another array, so I'll get 2 arrays at the end.
What I tried -
for (let j = 0; j < arr2.length; j++) {
for (let i = 0; i < arr.length; i++) {
const { name: name1, size: size1 } = arr[i];
const { name: name2, size: size2 } = arr2[j];
if (name1 === name2 && size1 === size2) {
x.push(arr.splice(i, 1)[0]);
break;
} else {
y.push(arr[i]);
}
}
}
Got in x -
[ { name: 'q', age: 10, size: 'M' }, { name: 'w', age: 10, size: 'S' } ]
Got in y -
[ { name: 'e', age: 10, size: 'M' },
{ name: 'e', age: 10, size: 'M' } ]
I should get in y -
[ { name: 'e', age: 10, size: 'M' } ]
Would love to get some help
Your inner loop cannot decide whether an element should be pushed to y, because not all values of arr2 have been iterated yet. Such a push can only happen when all those arr2 values have been considered.
As you don't remove the item from arr when it is pushed to y, it is no surprise it can be pushed a second time.
It is also problematic that you use splice in a loop over that same array. This means that indexes are skipped, and this could also be a source of wrong results.
One way to solve this, is to create a Set of the second array, of strings that uniquely define the name/size combination, for instance by joining them with a separator that will not occur in the size value. Then remains to iterate the first array and check if that name/size key is present in that set or not:
const arr = [{name: "q",age: 10,size: "M",},{name: "w",age: 10,size: "S",},{name: "e",age: 10,size: "M",},];
const arr2 = [{name: "q",age: 10,size: "M",},{name: "w",age: 10,size: "S",},{name: "i",age: 10,size: "S",},{name: "x",age: 10,size: "S",},];
const set = new Set(arr2.map(({name, size}) => size + "/" + name));
const x = [], y = [];
for (let obj of arr) {
(set.has(obj.size + "/" + obj.name) ? x : y).push(obj);
}
console.log("x:");
console.log(x);
console.log("y:");
console.log(y);
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'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.
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 .
I have an array of objects like this:
var myArray = [
{
name: "abc",
age: 23,
rank:208
},
{
name: "pqr",
age: 25,
rank:178
},
{
name: "xyz",
age: 21,
rank:108
}
];
I expected result:
var newArray = [['abc', 23, 208], ['pqr', 25, 178], ['xyz', 21, 108]];
I tried to find solution but don't know what to search on internet. Please help. Thanks in advance.
Use map, this allows it to be short and concise.
var newArray = myArray.map(function (item) {
return Object.keys(item).map(function (subitem) {
return item[subitem]
});
});
Or if you happen to be using ES2015 (a newer version of JavaScript):
let newArray = myArray.map(item => Object.values(item));
You could try something like this...
var myArray = [{
name: "abc",
age: 23,
rank: 208
}, {
name: "pqr",
age: 25,
rank: 178
}, {
name: "xyz",
age: 21,
rank: 108
}];
function convertToArrayOfArrays(arr) {
var newArray = [];
for (var i = 0; i < arr.length; i++) {
var arraySection = [];
var obj = arr[i];
for (var key in obj) {
arraySection.push(obj[key]);
}
newArray.push(arraySection);
}
return newArray;
}
console.log(convertToArrayOfArrays(myArray));
var result = [];
for (i in myArray){
var newArray = [];
for(j in myArray[i]){
newArray.push(myArray[i][j]);
}
result.push(newArray);
}