I'm trying to convert this
[ { "_id": "57760ecef5e7478c1e46b892" },
{ "_id": "57760f56f5e7478c1e46b896" },
{ "_id": "57760f7df5e7478c1e46b89a" } ]
to this
"_id" : [ "57760ecef5e7478c1e46b892", "57760f56f5e7478c1e46b896", "57760f7df5e7478c1e46b89a" ]
through code.
I am relatively new to the world of node.js so I don't know what to search for.
You can use the arrow functions of ES6 to do that in a very concise way:
var obj = {_id: yourArray.map((item) => item._id)}
See Arrow functions and map() for details.
var arrr = [{
"_id": "57760ecef5e7478c1e46b892"
}, {
"_id": "57760f56f5e7478c1e46b896"
}, {
"_id": "57760f7df5e7478c1e46b89a"
}]
var newObj = {
"_id": arrr.map(function(elem) {
return elem["_id"];
})
};
console.log(newObj);
Related
This question already has answers here:
Find all values by specific key in a deep nested object
(11 answers)
Closed 10 months ago.
I have this JSON array tree that can include any number of nested arrays:
const namesArrayTree = [
{
"name": "Peter"
},
{
"name": "folder1",
"isArray": true,
"namesArray": [
{
"name": "Paul"
},
{
"name": "folder2",
"isArray": true,
"namesArray": [
{
"name": "Mary"
},
{
"name": "John"
}
]
}
]
},
{
"name": "Mark"
}
]
I need to transform it to a flat array including only the names:
const namesArrayFlat = [ "Peter", "Paul", "Mary", "John", "Mark" ]
So I'm using this code to do the transformation:
const namesArrayTree = [
{
"name": "Peter"
},
{
"name": "folder1",
"isArray": true,
"namesArray": [
{
"name": "Paul"
},
{
"name": "folder2",
"isArray": true,
"namesArray": [
{
"name": "Mary"
},
{
"name": "John"
}
]
}
]
},
{
"name": "Mark"
}
] ;
function getNamesList(item) {
let name = item.name;
let isArray = item.isArray;
if (isArray) {
name = item.namesArray.map(getNamesList).join("\r\n");
}
return name;
}
const namesList = namesArrayTree.map(getNamesList).join("\r\n");
const namesArrayFlat = namesList.split("\r\n");
console.log(namesArrayFlat)
The code works well, but I would like to get rid of the extra steps to create a list with the names using join.("\r\n") and then convert to array using split("\r\n").
That is, I would like to reduce the code by removing the following:
function getNamesList(item) {
let name = item.name;
let isArray = item.isArray;
if (isArray) {
/* remove code to join by "\r\n" */
name = item.namesArray.map(getNamesList)
}
return name;
}
/* remove code to create "namesList" constant and remove code to join by "\r\n") */
const namesArrayFlat = namesArrayTree.map(getNamesList)
console.log(namesArrayFlat)
(The above code still returns a tree nested arrays structure)
Any ideas about how to get rid of the extra code? also any suggestions about how to improve the code would be great, thanks!
function getNamesList(item) {
return item.isArray ? item.namesArray.map(getNamesList) : item.name
}
const names = namesArrayTree.map(getNamesList).flat(Infinity)
console.log(names)
You can achieve this with an array reducer as follows:
const namesArray = [
{
"name": "Peter"
},
{
"name": "folder1",
"isArray": true,
"namesArray": [
{
"name": "Paul"
},
{
"name": "folder2",
"isArray": true,
"namesArray": [
{
"name": "Mary"
},
{
"name": "John"
}
]
}
]
},
{
"name": "Mark"
}
] ;
function reduceNamesList(list, item) {
if (item.isArray) {
return item.namesArray.reduce(reduceNamesList, list);
}
list.push(item.name)
return list
}
const namesList = namesArray.reduce(reduceNamesList, [])
console.log(namesList)
My target is if the id from digital_assets and products matches then get the value of URL fro digital_assets and ProductName from products object. I'm able to traverse through the object and get the values of digital_assets and products but need some help to compare these two objects based on IDs to get the value of URL and ProductName. Below is what I've done so far.
var data = [{
"digital_assets": [{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}]
}, {
"products": [{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},{
"id": ["BB002", "AA002"],
"ProductName": "PROD 555"
}]
}
];
$.each(data, function () {
var data = this;
//console.log(data);
$.each(data.digital_assets, function () {
var dAssets = this,
id = dAssets['id'];
// console.log(id);
});
$.each(data.products, function () {
var proData = this,
prod_id = proData['id'];
// console.log(prod_id);
$.each(prod_id, function () {
var arr_id = this;
console.log(arr_id);
});
});
});
Do I need to create new arrays and push the values into the new arrays? Then concat() these array to one. ? Bit lost any help will be appreciated.
Here is one way you can do this via Array.reduce, Array.includes, Object.entries and Array.forEach:
var data = [{ "digital_assets": [{ "id": "AA001", "url": "https://via.placeholder.com/150" }, { "id": "AA002", "url": "https://via.placeholder.com/150" } ] }, { "products": [{ "id": ["BB001", "AA001"], "ProductName": "PROD 485" }, { "id": ["BB002", "AA002"], "ProductName": "PROD 555" } ] } ]
const result = data.reduce((r,c) => {
Object.entries(c).forEach(([k,v]) =>
k == 'digital_assets'
? v.forEach(({id, url}) => r[id] = ({ id, url }))
: v.forEach(x => Object.keys(r).forEach(k => x.id.includes(k)
? r[k].ProductName = x.ProductName
: null))
)
return r
}, {})
console.log(Object.values(result))
You can use Array.prototype.find, Array.prototype.includes and Array.prototype.map to achieve this very gracefully.
let data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
];
// Find the 'digital_assets' array
let assets = data.find(d => d['digital_assets'])['digital_assets'];
// Find the 'products' array
let products = data.find(d => d['products'])['products'];
// Return an array of composed asset objects
let details = assets.map(a => {
return {
id : a.id,
url : a.url
name : products.find(p => p.id.includes(a.id)).ProductName
};
});
console.log(details);
changed answer to fit your needs:
var data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
]
let matchingIds = [];
let data_assetsObject = data.find(element => {
return Object.keys(element).includes("digital_assets")
})
let productsObject = data.find(element => {
return Object.keys(element).includes("products")
})
data_assetsObject["digital_assets"].forEach(da => {
productsObject["products"].forEach(product => {
if (product.id.includes(da.id)){
matchingIds.push({
url: da.url,
productName: product.ProductName
})
}
})
})
console.log(matchingIds);
working fiddle: https://jsfiddle.net/z2ak1fvs/3/
Hope that helped. If you dont want to use a new array, you could also store the respective data within the element you are looping through.
Edit:
I think i know why i got downvoted. My example works by making data an object, not an array. changed the snippet to show this more clearly.
Why is data an array anyway? Is there any reason for this or can you just transform it to an object?
Edit nr2:
changed the code to meet the expectations, as i understood them according to your comments. it now uses your data structure and no matter whats in data, you can now search for the objects containing the digital_assets / products property.
cheers
https://jsfiddle.net/2b1zutvx/
using map.
var myobj = data[0].digital_assets.map(function(x) {
return {
id: x.id,
url: x.url,
ProductName: data[1].products.filter(f => f.id.indexOf(x.id) > -1).map(m => m.ProductName)
};
});
I have this sought of array
{
"arr": [
{
"obj": [
{
"reg_at": 1519615460064,
"id": "367790083"
},
{
"reg_at": 1519615460064,
"id": "41370460"
}
]
},
{
"obj": [
{
"reg_at": 1519615460065,
"id": "215109021"
},
{
"reg_at": 1519615460065,
"id": "72173002"
}
]
}
]
}
and i want to all the id objects into one array like this:
[367790083, 41370460, 41370460]
please how do i go about achieving this using nodejs? i have tried looping through but am not getting the desired output.
Thanks for your help.
Use reduce and map
var output = obj.arr.reduce( (a, c) =>
a.concat( c.obj.map(
s => +s.id ) ) , [])
Explanation
Use reduce to iterate and accumulate the output to a
Use map to return the id (number converted) of every item in obj array inside arr
Demo
var obj = {
"arr": [
{
"obj": [
{
"reg_at": 1519615460064,
"id": "367790083"
},
{
"reg_at": 1519615460064,
"id": "41370460"
}
]
},
{
"obj": [
{
"reg_at": 1519615460065,
"id": "215109021"
},
{
"reg_at": 1519615460065,
"id": "72173002"
}
]
}
]
};
var output = obj.arr.reduce( (a, c) =>
a.concat( c.obj.map(
s => +s.id ) ) , []);
console.log( output );
Seeing that you are a beginner I'll do this the good old fashioned way for you to understand how the data is organized.
var data = {
"arr": [
{
"obj": [
{
"reg_at": 1519615460064,
"id": "367790083"
},
{
"reg_at": 1519615460064,
"id": "41370460"
}
]
},
{
"obj": [
{
"reg_at": 1519615460065,
"id": "215109021"
},
{
"reg_at": 1519615460065,
"id": "72173002"
}
]
}
]
};
// The variable for the result
var result = [];
// "data" is the object and "arr" is an array and has a length
for (var i=0; i<data.arr.length; i++) {
// For clarity, pick the current object from the array
var theArrItem = data.arr[i];
// That object then has a "obj" which is an array
for (var j=0; j<theArrItem.obj.length; j++) {
// Again, pick the current object
var theObjItem = theArrItem.obj[j];
// Add the id of the current object to the result
result.push(theObjItem.id);
}
}
console.log(result);
You can simply use lodash library as it has many inbuilt functions that can reduce coding on server side.
npm i --save lodash
_.map(arr, 'id');
Result will be [367790083, 41370460, 41370460]
I'd like to transform this array to another array using lodash 2.4.2:
authorities will be mapped in roles. and we don't touch the other properties.
From:
{
"items": [
{
"_id": "admin",
"authorities": [
{
"name": "ROLE_ADMIN"
}
]
},
{
"_id": "user",
"authorities": [
{
"name": "ROLE_USER"
}
]
}
]
}
to this array
{
"items": [
{
"_id": "admin",
"roles": [
"ROLE_ADMIN"
]
},
{
"_id": "user",
"role": [
"ROLE_USER"
]
}
]
}
can you help me please?
As charlietfl said, in the future posts you must provide examples of code, that you've written to solve your problem.
Here's the solution, it's pretty simple:
const initialObject = {
"items": [
{
"_id": "admin",
"authorities": [
{
"name": "ROLE_ADMIN"
}
]
},
{
"_id": "user",
"authorities": [
{
"name": "ROLE_USER"
}
]
}
]
}
const processedObject = _
.map(initialObject.items, item => {
return {
_id: item._id,
roles: _.map(item.authorities, a => a.name)
}
})
It is just a re-mapping of the key name. For performance reasons I would try to avoid the use of delete. You can see the performance differences in this benchmark, only use 'delete' if the object gets persisted later on.
for (var item of items) {
item.roles = item.authorities
// possible but slow
// delete item.authorities
item.authorities = undefined
}
Edit: #vanelizarov code is even better if you want to avoid mutation of the object itself and clean properties. but it is also slower.
vanelizarov code: x 5,025,370 ops/sec ±1.30% (90 runs sampled)
my code: x 31,583,811 ops/sec ±0.95% (92 runs sampled)
So I have a bunch of status codes, in an object (from an API) that returns like this:
{
"location": [
"HOME_ADDRESS_INCOMPLETE",
"HOME_MISSING_ADDRESS"
],
"basics": [
"HOME_MISSING_TYPE"
],
"description": [
"HOME_MISSING_DESCRIPTION"
],
"immersions": [
"AT_LEAST_ONE_STAY_REQUIRED",
"SIMPLE_STAY_MISSING_HOURS",
"SIMPLE_STAY_MISSING_OFFERED_LANGUAGES",
"TANDEM_STAY_MISSING_HOURS",
"TANDEM_STAY_MISSING_OFFERED_LANGUAGES",
"TANDEM_STAY_MISSING_INTERESTED_LANGUAGES",
"TEACHER_STAY_MISSING_HOURLY_PRICE",
"TEACHER_STAY_MISSING_OFFERED_LANGUAGES",
"TEACHER_STAY_MISSING_WEEKLY_PACKAGES"
],
"rooms": [
"NO_ROOMS"
],
"photos": [
"AT_LEAST_ONE_HOME_IMAGE_REQUIRED"
],
"pricing": [
"MISSING_CURRENCY",
"SERVICE_WITHOUT_PRICE",
"DISCOUNT_WITHOUT_PERCENT",
"ROOM_WITHOUT_PRICE"
]
}
The key names, like location correlate to a step in a setup wizard that the user must be placed on depending on what is missing, which is represented by constants like HOME_ADDRESS_INCOMPLETE.
What is the most terse or clear way to start with this object and one constant, like MISSING_CURRENCY, and return the name of the key to which that constant's array belongs to?
Here's what I have so far, but all it does is return the array itself:
const activeStep = Object.values(HomeStatusCodes).filter(statusArray => {
return statusArray.includes(homeActivationResponse.code)
})
Array#find (on the array of keys of that structure, from Object.keys) plus Array#indexOf should do it:
function find(value) {
return Object.keys(data).find(function(key) {
return data[key].indexOf(value) != -1;
});
}
Note that Array#find is new in ES2015, but can readily be shimmed/polyfilled.
Example:
var data = {
"location": [
"HOME_ADDRESS_INCOMPLETE",
"HOME_MISSING_ADDRESS"
],
"basics": [
"HOME_MISSING_TYPE"
],
"description": [
"HOME_MISSING_DESCRIPTION"
],
"immersions": [
"AT_LEAST_ONE_STAY_REQUIRED",
"SIMPLE_STAY_MISSING_HOURS",
"SIMPLE_STAY_MISSING_OFFERED_LANGUAGES",
"TANDEM_STAY_MISSING_HOURS",
"TANDEM_STAY_MISSING_OFFERED_LANGUAGES",
"TANDEM_STAY_MISSING_INTERESTED_LANGUAGES",
"TEACHER_STAY_MISSING_HOURLY_PRICE",
"TEACHER_STAY_MISSING_OFFERED_LANGUAGES",
"TEACHER_STAY_MISSING_WEEKLY_PACKAGES"
],
"rooms": [
"NO_ROOMS"
],
"photos": [
"AT_LEAST_ONE_HOME_IMAGE_REQUIRED"
],
"pricing": [
"MISSING_CURRENCY",
"SERVICE_WITHOUT_PRICE",
"DISCOUNT_WITHOUT_PERCENT",
"ROOM_WITHOUT_PRICE"
]
};
function find(value) {
return Object.keys(data).find(function(key) {
return data[key].indexOf(value) != -1;
});
}
console.log(find("MISSING_CURRENCY"));
Even more terse when you use ES2015 syntax:
const find = value =>
Object.keys(data).find(key => data[key].indexOf(value) != -1);
(Yes, that's really a function.) Here's a live version of that for browsers that support ES2015:
var data = {
"location": [
"HOME_ADDRESS_INCOMPLETE",
"HOME_MISSING_ADDRESS"
],
"basics": [
"HOME_MISSING_TYPE"
],
"description": [
"HOME_MISSING_DESCRIPTION"
],
"immersions": [
"AT_LEAST_ONE_STAY_REQUIRED",
"SIMPLE_STAY_MISSING_HOURS",
"SIMPLE_STAY_MISSING_OFFERED_LANGUAGES",
"TANDEM_STAY_MISSING_HOURS",
"TANDEM_STAY_MISSING_OFFERED_LANGUAGES",
"TANDEM_STAY_MISSING_INTERESTED_LANGUAGES",
"TEACHER_STAY_MISSING_HOURLY_PRICE",
"TEACHER_STAY_MISSING_OFFERED_LANGUAGES",
"TEACHER_STAY_MISSING_WEEKLY_PACKAGES"
],
"rooms": [
"NO_ROOMS"
],
"photos": [
"AT_LEAST_ONE_HOME_IMAGE_REQUIRED"
],
"pricing": [
"MISSING_CURRENCY",
"SERVICE_WITHOUT_PRICE",
"DISCOUNT_WITHOUT_PERCENT",
"ROOM_WITHOUT_PRICE"
]
};
const find = value =>
Object.keys(data).find(key => data[key].indexOf(value) != -1);
console.log(find("MISSING_CURRENCY"));
You could iterate the keys and find the one which property includes the wanted item.
function getKey(object, item) {
return Object.keys(object).find(k => object[k].includes(item));
}
var data = { "location": ["HOME_ADDRESS_INCOMPLETE", "HOME_MISSING_ADDRESS"], "basics": ["HOME_MISSING_TYPE"], "description": ["HOME_MISSING_DESCRIPTION"], "immersions": ["AT_LEAST_ONE_STAY_REQUIRED", "SIMPLE_STAY_MISSING_HOURS", "SIMPLE_STAY_MISSING_OFFERED_LANGUAGES", "TANDEM_STAY_MISSING_HOURS", "TANDEM_STAY_MISSING_OFFERED_LANGUAGES", "TANDEM_STAY_MISSING_INTERESTED_LANGUAGES", "TEACHER_STAY_MISSING_HOURLY_PRICE", "TEACHER_STAY_MISSING_OFFERED_LANGUAGES", "TEACHER_STAY_MISSING_WEEKLY_PACKAGES"], "rooms": ["NO_ROOMS"], "photos": ["AT_LEAST_ONE_HOME_IMAGE_REQUIRED"], "pricing": ["MISSING_CURRENCY", "SERVICE_WITHOUT_PRICE", "DISCOUNT_WITHOUT_PERCENT", "ROOM_WITHOUT_PRICE"] };
console.log(getKey(data, 'MISSING_CURRENCY'));
I'd go for a lookup map:
const stepByStatusCode = new Map()
for (const step in HomeStatusCodes) {
for (const code of HomeStatusCodes[step])
stepByStatusCode.set(code, step);
which you then can use in the most terse way
const activeStep = stepByStatusCode.get(homeActivationResponse.code);