How to destructure array inside object in js? [duplicate] - javascript

This question already has an answer here:
ES6 deep nested object destructuring
(1 answer)
Closed 3 days ago.
How to destructure array inside object in js?
let data = {
names: ["Sam", "Tom", "Ray", "Bob"],
ages: [20, 24, 22, 26],
};
let /* some code */ = data;
console.log(name2); // "Tom"
console.log(age2); // 24
console.log(name4); // "Bob"
console.log(age4); // 26

Since they're arrays you need to use [], not {} in the destructure to mirror the original data structure.
const data = {
names: ["Sam", "Tom", "Ray", "Bob"],
ages: [20, 24, 22, 26],
};
const {
names: [ , name2, , name4 ],
ages: [ , age2, , age4 ]
} = data;
console.log(name2);
console.log(age2);
console.log(name4);
console.log(age4);

let data = {
names: ["Sam", "Tom", "Ray", "Bob"],
ages: [20, 24, 22, 26],
};
console.log(data.names[0]); // "Sam"
console.log(data.ages[0]); // 20
console.log(data.names[3]); // "Bob"
console.log(data.ages[3]); // 26

You need to use the variable names in the same structure for destructuring.
const
data = {
names: ["Sam", "Tom", "Ray", "Bob"],
ages: [20, 24, 22, 26],
},
{
names: [name1, name2, name3, name4],
ages: [age1, age2, age3, age4]
} = data;
console.log(name2); // "Tom"
console.log(age2); // 24
console.log(name4); // "Bob"
console.log(age4); // 26

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

Combine 2 Arrays in 2D Array if one parameter is the same

The problem I have is, that I want to combine a 2D Array like this:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 32, 12, … ],
[ "Mercedes", 24, 21, … ],
[ "Toro Rosso", 7, 8, … ]
]
So in this example I have the String "Mercedes" twice at index 0 in the arrays.
What I want the output to be is the following:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 56, 33, … ],
[ "Toro Rosso", 7, 8, … ]
]
So if a String like "Mercedes" is appearing twice in that array I want the second one to be deleted. But the values from the second array must be taken over into the first "Mercedes" Array.
It seems that you actually want to aggregate similar values in the array. Therefore you could do a cycle in foreach and save yourself in a temporary array the string values already known and instead in another your merged classes. At that point, as you scroll through your array, you can check if you have already added an equal string in the first fake, and if so, you can take its index and aggregate them correctly in the other array.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
var tmp1 = [], tmp2 = [];
arr.forEach(function(currentValue, index, arr) {
// currentValue contain your element
// index contain the index of your element
// arr contain you entire "values" array
var ind = tmp1.indexOf(currentValue[0]);
if(ind === -1) {
tmp1.push(currentValue[0]);
tmp2.push(currentValue);
} else {
tmp2[ind][1] += currentValue[1];
tmp2[ind][2] += currentValue[2];
}
});
console.log(tmp2);
You can use reduce() to build a object and then use Object.values()
const arr = [
[ "Renault", 61, 16 ],
[ "Ferrari", 58, 10],
[ "Mercedes", 32, 12],
[ "Mercedes", 24, 21],
[ "Toro Rosso", 7, 8]
]
let res = arr.reduce((ac, [k, ...rest]) => {
if(!ac[k]) ac[k] = [];
ac[k] = ac[k].concat(k,...rest);
return ac;
},[])
console.log(Object.values(res))
Sure, by creating an array for your names and then separate the unique ones from them, at last, match them with the index.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
let c = [...new Set(arr.map(a => a[0]))] // get unique values of all arr[0]
let ans = arr.filter((a, post) => {
if (c[post]) { // check if index exists because we seperated one, the last is undefined here
if (a[0] == c[post]) {
return a;
}
} else {
return a; // else return as usual
}
})
console.log(ans)
You get the filtered array.
You can iterate over the array and keep a map object of the names you already processed with their index in the result array so you can access them quicker when you need to push more values.
i.e:
{
"Renault": 0,
"Ferrari": 1,
"Mercedes": 2,
"ToroRosso": 3
}
Here is a running example with the steps:
const arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
];
let map = {};
let globalIndex = 0;
let resultArray = [];
arr.forEach((currentArray) => {
const [name, ...rest] = currentArray;
if (map[name] === undefined) {
// if our map doesn't already store this value
// then store it with it's current index
map[name] = globalIndex;
// push it to the result array
resultArray[globalIndex] = currentArray;
// increment the global index
//so we can keep track of it in the next iteration
globalIndex++;
} else {
// we already have an array with this name
// grab the relevant index we previously stored
// and push the items without the name via this index
const relevantIdx = map[name];
resultArray[relevantIdx] = [
...resultArray[relevantIdx],
...rest
]
}
})
console.log(resultArray);

Weird hiccup removing duplicates from an array

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.

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 .

LoDash: Get an array of values from an array of object properties

I'm sure it's somewhere inside the LoDash docs, but I can't seem to find the right combination.
var users = [{
id: 12,
name: 'Adam'
},{
id: 14,
name: 'Bob'
},{
id: 16,
name: 'Charlie'
},{
id: 18,
name: 'David'
}
]
// how do I get [12, 14, 16, 18]
var userIds = _.map(users, _.pick('id'));
Since version v4.x you should use _.map:
_.map(users, 'id'); // [12, 14, 16, 18]
this way it is corresponds to native Array.prototype.map method where you would write (ES2015 syntax):
users.map(user => user.id); // [12, 14, 16, 18]
Before v4.x you could use _.pluck the same way:
_.pluck(users, 'id'); // [12, 14, 16, 18]
In the new lodash release v4.0.0 _.pluck has removed in favor of _.map
Then you can use this:
_.map(users, 'id'); // [12, 14, 16, 18]
You can see in Github Changelog
With pure JS:
var userIds = users.map( function(obj) { return obj.id; } );
And if you need to extract several properties from each object, then
let newArr = _.map(arr, o => _.pick(o, ['name', 'surname', 'rate']));
Simple and even faster way to get it via ES6
let newArray = users.flatMap(i => i.ID) // -> [ 12, 13, 14, 15 ]
If you are using native javascript then you can use this code -
let ids = users.map(function(obj, index) {
return obj.id;
})
console.log(ids); //[12, 14, 16, 18]
const users = [{
id: 12,
name: 'Adam'
},{
id: 14,
name: 'Bob'
},{
id: 16,
name: 'Charlie'
},{
id: 18,
name: 'David'
}
]
const userIds = _.values(users);
console.log(userIds); //[12, 14, 16, 18]
This will give you what you want in a pop-up.
for(var i = 0; i < users.Count; i++){
alert(users[i].id);
}

Categories