Weird hiccup removing duplicates from an array - javascript

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.

Related

How to join 2 arrays into an array of objects

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);

Question regarding swapping key/value of objects

I want to swap the key/value content of Jacob with the key/value content of Guillermo
I was able to swap Guillermo to Jacob but not the other way around.
This is my code which is only half correct:
let students = {
jacob: {
classes: ["math", "chemistry", "english"],
grade: 11,
age: 16,
},
guillermo: {
classes: ["history", "math", "physics"],
grade: 12,
age: 17,
},
};
let temp = students.jacob;
students.guillermo = temp;
let temp1 = students.guillermo;
students.jacob = temp1;
console.log(students)
You need to copy before re-assigning
let students = {
jacob: {
classes: ["math", "chemistry", "english"],
grade: 11,
age: 16,
},
guillermo: {
classes: ["history", "math", "physics"],
grade: 12,
age: 17,
},
};
let temp = students.jacob;
let temp1 = students.guillermo;
students.guillermo = temp;
students.jacob = temp1;
console.log(students)

How to push an array with objects into an array

I am a newbie here so my question may sound stupid.
I have an array with multiple objects and I am not sure how to push the key name of each object to an array.
This is my code:
var ingredients = [
{ id: 1, name: "onion", mineralsUnit: "mg", water: 89.11 },
{ id: 2, name: "carrot", calcium: 23, iron: 0.21, otherUnit: "g", water: 89.11 },
{ id: 3, name: "peanut", iron: 0.21, otherUnit: "g", water: 89.11 }
];
and I've created a new empty array where I want to add just the name from the first array
var myIngredients = [];
I've tried that:
for (var i = 0; i < ingredients.length; i++) {
myIngredients.push(ingredients[i]);
}
but it returns the entire array and even though I select in here ingredients[I] what element I want to pick it's still not working.
If someone has an idea I would really appreciate it. Thanks a lot.
with es6 you can use map
try myIngredients = ingredients.map(ingredient => ingredients.name)
You were very close. This will push the name value of every object in the ingredients array
for (var i = 0; i < ingredients.length; i++) {
myIngredients.push(ingredients[i].name);
}
Just don't forget the comma after peanut!
var myIngredients = [];
ingredients.forEach(
ingredient =>
myIngredients.push(ingredient.name)
)
console.log(myIngredients)
You can use the map function:
var ingredients = [
{ id: 1, name: "onion", mineralsUnit: "mg", water: 89.11},
{ id: 2, name: "carrot", calcium: 23, iron: 0.21, otherUnit: "g", water: 89.11 },
{ id: 3, name: "peanut", iron: 0.21, otherUnit: "g", water: 89.11, }
];
var myIngredients = ingredients.map(e => e.name);
console.log(myIngredients);

return array of object javascript

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 .

JavaScript - Convert an Array of Objects with Key-value pair to Array of Arrays with values

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);
}

Categories