I am new in javascript and using nodejs and mongoose query to get a result which I would like to loop through and get some values in another array.
The resultset looks like
[ { _id: 5366e9049cfc825b32966852,
companies:
[ 5ab20bb69cb2754e949a09dc,
5ac5d53983d45353bc6a9c54,
5ac62eeca5421e4cb9abf63e]
},
{ _id: 5b9251f8ae8db624755f4b90,
companies:
[ 5b461c892bb9c81bd3ed4a25,
5b5086196947782fbc873d28,
5b76a6c79dc71a4a12564cc5 ]
}]
The final array should look like --
[ 5ab20bb69cb2754e949a09dc,
5ac5d53983d45353bc6a9c54,
5ac62eeca5421e4cb9abf63e,
5b461c892bb9c81bd3ed4a25,
5b5086196947782fbc873d28,
5b76a6c79dc71a4a12564cc5]
My code--
Model.find().exec(function(err,gdoc){
if(err)
{
callback({err:err,message:"Error looking up company"});
}else
{
for (var i = 0, len = gdoc.length; i < len; i++) {
console.log(gdoc.companies);
}
}
});
I am getting undefined values.
Any help is highly appreciated. Thanks in advance.
The reason why you are getting undefined is that you try to access the non-existing companies property on gdoc. Instead of gdoc.companies, you have to use gdoc[i].companies.
Instead of your loop, you can use Array.prototype.concat together with the spread syntax (...) and Array.prototype.map as follows:
const gdoc = [
{
_id: '5366e9049cfc825b32966852',
companies: [
'5ab20bb69cb2754e949a09dc',
'5ac5d53983d45353bc6a9c54',
'5ac62eeca5421e4cb9abf63e',
],
},
{
_id: '5b9251f8ae8db624755f4b90',
companies: [
'5b461c892bb9c81bd3ed4a25',
'5b5086196947782fbc873d28',
'5b76a6c79dc71a4a12564cc5',
],
},
];
const companies = [].concat(...gdoc.map(doc => doc.companies));
console.log(companies);
Basically you're trying to concatenate all the company fields of the results array. As long as you know that the key is companies, this is an easy reduction.
Arrays have a couple of builtin methods that make transforming them very easy, compared to having to use a for-loop.
Array.forEach(), Array.map(), Array.reduce() and Array.find() are the most frequently used ones.
// Since these id's contain letters as well, they need to be strings.
const data = [
{
_id: "5366e9049cfc825b32966852",
companies:[
"5ab20bb69cb2754e949a09dc",
"5ac5d53983d45353bc6a9c54",
"5ac62eeca5421e4cb9abf63e"
]
},
{
_id: "5b9251f8ae8db624755f4b90",
companies:[
"5b461c892bb9c81bd3ed4a25",
"5b5086196947782fbc873d28",
"5b76a6c79dc71a4a12564cc5"
]
}
];
const companies = data.reduce(( result, item ) => result.concat( item.companies ), []);
console.log( companies );
You can use the following method:
const map = [...[].concat(...arr.map((o) => o.companies))]
var arr = [ { _id: "5366e9049cfc825b32966852",
companies:
[ "5ab20bb69cb2754e949a09dc",
"5ac5d53983d45353bc6a9c54",
"5ac62eeca5421e4cb9abf63e"]
},
{ _id: "5b9251f8ae8db624755f4b90",
companies:
[ "5b461c892bb9c81bd3ed4a25",
"5b5086196947782fbc873d28",
"5b76a6c79dc71a4a12564cc5" ]
}];
const map = [...[].concat(...arr.map((o) => o.companies))]
console.log(map);
How about running a reduce over the array.
const model = [{
_id: "5366e9049cfc825b32966852",
companies: [
"5ab20bb69cb2754e949a09dc",
"5ac5d53983d45353bc6a9c54",
"5ac62eeca5421e4cb9abf63e"
]
},
{
_id: "5b9251f8ae8db624755f4b90",
companies: [
"5b461c892bb9c81bd3ed4a25",
"5b5086196947782fbc873d28",
"5b76a6c79dc71a4a12564cc5"
]
}
];
const reducer = (acc, value) => {
acc.push(...value.companies);
return acc;
};
console.log(model.reduce(reducer, []));
You can do some thing like that!
var docs= [ { _id: "5366e9049cfc825b32966852",
companies:
[ "5ab20bb69cb2754e949a09dc",
"5ac5d53983d45353bc6a9c54",
"5ac62eeca5421e4cb9abf63e"]
},
{ _id: "5b9251f8ae8db624755f4b90",
companies:
[ "5b461c892bb9c81bd3ed4a25",
"5b5086196947782fbc873d28",
"5b76a6c79dc71a4a12564cc5" ]
}];
// your companies will be put in the folowing variable
var companies = [];
for ( var doc of docs){
for (var item of doc.companies){
companies.push(item)
}
}
console.log(companies)
const data = [ { _id: '5366e9049cfc825b32966852',
companies:
[ '5ab20bb69cb2754e949a09dc',
'5ac5d53983d45353bc6a9c54',
'5ac62eeca5421e4cb9abf63e']
},
{ _id: '5b9251f8ae8db624755f4b90',
companies:
[ '5b461c892bb9c81bd3ed4a25',
'5b5086196947782fbc873d28',
'5b76a6c79dc71a4a12564cc5' ]
}]
let outputArr = []
data.map(d => outputArr.push(d.companies));
//Flatten
console.log([].concat.apply([],outputArr))
Both flatMap and flat which are currently an 'experimental technology' will allow a cleaner approach to this problem in the future.
See:
Array.prototype.flat(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
Array.prototype.flatMap(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
You want something like this:
var k = [{
_id: "5366e9049cfc825b32966852",
companies: ["5ab20bb69cb2754e949a09dc",
"5ac5d53983d45353bc6a9c54",
"5ac62eeca5421e4cb9abf63e"
]
},
{
_id: "5b9251f8ae8db624755f4b90",
companies: ["5b461c892bb9c81bd3ed4a25",
"5b5086196947782fbc873d28",
"5b76a6c79dc71a4a12564cc5"
]
}
];
var res = [];
k.forEach(function(id) {
res.push(...id.companies)
});
console.log(res);
Related
Given de following arrays:
const classes = [
{
students: [
Student1,
Student2,
]
},
{
students: [
Student3,
Student4,
]
}
]
What's the best way performance-wise to generate an array of objects with a similar structure to this:
const allStudents = [
Student1,
Student2,
Student3,
Student4
]
Please note: Donot use reserved keyworks such ass class as a variable name.
Array.reduce implementation
const classes = [
{ students: [ 'Student1', 'Student2' ] },
{ students: [ 'Student3', 'Student4' ] }
];
const allStudents = classes.reduce((acc, cls) => {
acc = cls.students ? acc.concat(cls.students) : acc;
return acc;
}, []);
console.log(allStudents)
Array.flatMap implementation.
const classes = [
{ students: [ 'Student1', 'Student2' ] },
{ students: [ 'Student3', 'Student4' ] }
]
const allStudents = classes.flatMap((cls) => cls.students ? cls.students : []);
console.log(allStudents);
const classes = [
{
students:[
"Student1",
"Student2"
]
},
{
students:[
"Student3",
"Student4"
]
}
]
const n=classes.flatMap(x=>x.students.flatMap(i=>i))
console.log(n)
This would be recommended keeping performance in mind it is faster then regular for loop and ... many online sources say flatMap is better in terms of performance
const classes = [
{
students: ['Student1', 'Student2'],
},
{
students: ['Student3', 'Student4'],
},
];
const allStudents = classes.reduce((acc, curr) => {
return [...acc, ...curr.students];
}, []);
console.log(allStudents);
const allStudents = classes.reduce((acc,curr)=>{
return [...acc,...curr.students]
},[])
I think this is a simple and easy to understand way to group students in one array.
That's what I did, hope it helped:
const classes = [
{
students: [
'Student1',
'Student2',
]
},
{
students: [
'Student3',
'Student4',
]
}
];
var newArray = [];
for(var i = 0; i < classes.length; i++){
var tempArray = Object.values(classes[i]);
for(var j = 0; j < tempArray[0].length; j++){
newArray.push(tempArray[0][j]);
}
}
console.log(newArray);
So I have an array of objects called products:
const products = [
{
name: 'Pants'
},
{
name: 'Shoes'
},
{
name: 't shirts'
}
]
And the list contains a lot more products with other values apart from name. So suppose i forgot to give each product, (object) a coupon's array, it would take me quite a while to update each object manually.
Is there a function that I can create which will push a coupons value into each object as an array?
So the final array would look like:
const updatedProducts = [
{
name: 'Pants',
coupons: []
},
{
name: 'Shoes',
coupons: []
},
{
name: 't shirts',
coupons: []
}
]
const updatedProducts = products.map(product => ({ ...product, coupons: [] }))
Yes you can add properties in javascript like this:
products.forEach(product => product.coupons = []);
I have an array with objects and in each object there is an "items" array. My goal is to combine these "items" into one array.
Goal / Expected Output
[
{ id: 'SUV' },
{ id: 'Compact' },
{ id: 'Gasoline' },
{ id: 'Hybrid' }
]
Sample Array
[
{
"id":"carType",
"items":[
{
"id":"SUV"
},
{
"id":"Compact"
}
]
},
{
"id":"fuelType",
"items":[
{
"id":"Gasoline"
},
{
"id":"Hybrid"
}
]
}
]
You could use Array#flatMap.
const data = [{"id":"carType","items":[{"id":"SUV"},{"id":"Compact"}]},{"id":"fuelType","items":[{"id":"Gasoline"},{"id":"Hybrid"}]}];
const r = data.flatMap(({ items }) => items);
console.log(r);
A one-liner in vanilla JS (earlier than EMCAScript 2019, flatMap is not available, so in case of that...)
[].concat(...arr.map(elt => elt.items))
Something like this?
newArr = []
for (let i = 0;i<arr.length;i++) {
for (let ii = 0;ii<arr[i].items.length;ii++) {
newArr.push(arr[i].items[ii].id)
}
}
console.log(newArr)
I have the following data and I am stuck between a logic
[
{
"user.employeeId": "10081",
"objectives": [
"Improve consultation"
],
"param": "dueByDays"
},
{
"user.employeeId": "10081",
"objectives": [
"Building a strong team"
],
"param": "overdue"
},
]
How can I get the data in the below format, I have tried Map(), ForEach(), etc. but I am getting stuck,
This is the requirement/Output
[
{
'user.employeeId': '10081',
params: [
{
objectives: ['Improve consultation'],
param: 'dueByDays'
},
{
objectives: ['Building a strong team'],
param: 'overdue'
},
{
objectives: null,
param: 'dueToday'
}
]
}];
If suppose param is not available, we still need to set objective as null, please help me out regarding this query. It would be better if anyone can help me do this using lodash
There will be only 3 params as mentioned above
The approach here would be something like this:
create some "storage" object (can be a simple object);
iterate through items;
if this is a new employee, then create new record in the "storage";
if this is a known employee, just update its info.
After this, the storage object has to be converted to an array, as per requirement:
const userEntries = /* initial array */;
const tempStorage = Object.create(null); // or just '{}'
for (const entry of userEntries) {
const id = entry["user.employeeId"];
const param = {
objectives: entry.objectives,
param: entry.param,
};
if (id in tempStorage === false) { // this is a new employee
tempStorage[id] = [ param ];
} else { // this is a known employee, it exists in storage
tempStorage[id].push(param);
}
}
// All the necessary data is in tempStorage.
// Now on to converting.
const output = [];
for (const employeeId in tempStorage) {
output.push({
["user.employeeId"]: employeeId,
params: tempStorage[employeeId],
});
}
Something like this should work:
const employeesData = {};
for (let item of array) {
const id = item["user.employeeId"];
if (!employeesData[id]) {
employeesData[id] = {};
}
employeesData[id][item.param] = item.objectives;
}
const params = ['dueByDays', 'overdue', 'dueToday'];
const result = [];
for (let key of Object.keys(employeesData)) {
result.push({
'user.employeeId': key,
params: params.map(param => ({
param,
objectives: employeesData[key][param] || null,
})),
});
}
We first build an object containing all the data then we iterate through the keys to build a proper array.
I don't test it but it should work.
const usersHash = users.reduce((acc, curr) => {
if(acc[curr["user.employeeId"]])
acc[curr["user.employeeId"]].params.push(curr.param ? {...curr.param} : {})
else
acc[curr["user.employeeId"]] = { "user.employeeId": curr["user.employeeId"], params: [{...curr.param}] }
return acc;
},{})
const mergedUsers = Object.values(usersHash);
You can use .reduce() method. The following code should work.
const arr = [
{
"user.employeeId": "10081",
"objectives": [
"Improve consultation"
],
"param": "dueByDays"
},
{
"user.employeeId": "10081",
"objectives": [
"Building a strong team"
],
"param": "overdue"
},
{
"user.employeeId": "10081",
"objectives": [
"A team"
],
},
]
const result = arr.reduce((accumulator, currentValue) => {
const element = accumulator.find(item => item['user.employeeId'] === currentValue['user.employeeId'])
if (element) {
element.params.push({objectives: currentValue.objectives, param: currentValue.param || null})
} else {
accumulator.push({'user.employeeId': currentValue['user.employeeId'], params: [{objectives: currentValue.objectives, param: currentValue.param || null}]})
}
return accumulator
},[])
console.log(result)
Let's say I have the following:
[
{ messageid: '582b4350af7cb8f21e4b7b43',
_id: 582b4c79105387dd21e08004 } ,
{ messageid: '582b4350af7cb8f21e4b7xb43',
_id: 582b4c79105387dd21e08s004 }
]
How can I make it produce a array that would only be the messageid `s values?
Like:
{582b4350af7cb8f21e4b7b43,582b4350af7cb8f21e4b7xb43} ?
Note: plain javascript or angular
You can use .map
var output = input.map(function(item) {
return item.messageid;
});
This will create an array that will look like [582b4350af7cb8f21e4b7b43,582b4350af7cb8f21e4b7xb43]
You could map the property messageid.
var objectArray = [{ messageid: '582b4350af7cb8f21e4b7b43', _id: '582b4c79105387dd21e08004' }, { messageid: '582b4350af7cb8f21e4b7xb43', _id: '582b4c79105387dd21e08s004' }],
newArray = objectArray.map(function (o) {
return o.messageid;
});
console.log(newArray);
Use forEach to loop through the array
var orArray = [{
messageid: '582b4350af7cb8f21e4b7b43',
_id: '582b4c79105387dd21e08004'
}, {
messageid: '582b4350af7cb8f21e4b7xb43',
_id: '582b4c79105387dd21e08s004'
}
];
var newArr = [];
orArray.forEach(function(item) {
newArr.push(item.messageid)
});
console.log(newArr)
DEMO