Normal Mapping vs Reduce - javascript

I'm trying to convert an object into single array with just key and value. I tried two different ways. Though I succeeded in my first attempt but using reduce I am unable to get the result. Please kindly let me know if there is/are better ways of achieving the same. Thank you.
var demoArr = [
{
"results": [
{
"listing_id": 10544193
},
{
"listing_id": 4535435
}
],
"results1": [
{
"listing_id": 1054419363
},
{
"listing_id": 432535435
}
]
}
];
let aaa = [];
// demoArr.map(x => { (before)
demoArr.forEach(x => { //(after)
let ss = Object.values(x);
// ss.map(y => { (before)
ss.forEach(y => { //(after)
y.forEach(k => {
aaa.push({"listing_id" : k.listing_id});
})
});
});
Resulted in the following.
[{"listing_id":10544193},{"listing_id":4535435},{"listing_id":1054419363},{"listing_id":432535435}]
Is there a better way to achieve the above? Maybe by using reduce? I tried but failed to get the result.
var ds = demoArr.reduce((a,value) => {
a[value.listing_id] = a[value.listing_id] ? a[value.listing_id] : value
return a
},{});

Here's one way use flatMap() and Object.values, then flatten the result. Using Object.values as an argument in this fashion is a shorthand for applying the map argument directly into the Object.values method and returning the result
var demoArr = [{
"results": [{
"listing_id": 10544193
},
{
"listing_id": 4535435
}
],
"results1": [{
"listing_id": 1054419363
},
{
"listing_id": 432535435
}
]
}];
let output = demoArr.flatMap(Object.values).flat();
console.log(output)

Related

Update array object in foreach loop with javascript

I am trying to create a new array.
I have list of plugins with different versions, and I need to find plugins with same uniqueIdentifier but different versions, and create one array out of it.
Example:
{
"uniqueIdentifier": "theme_test",
"version": "2011120800"
},
{
"uniqueIdentifier": "theme_test",
"version": "3011120800"
},
{
"uniqueIdentifier": "theme_test",
"version": "4011120800"
},
to be like this:
{
"uniqueIdentifier": "theme_test",
"version": [
"2011120800",
"3011120800",
"4011120800"
]
}
So, in my code I am getting all the information, but I cannot make it work to store this versions as an array. So I am checking the uniqueIdentifier and then the version, and trying to generate new array:
item.pluginVersions.items.forEach(function(plugin) {
pluginVersionsSupported.forEach(function(supportedPlugin) {
if (plugin.uniqueIdentifier === supportedPlugin.uniqueIdentifier) {
if (plugin.version == supportedPlugin.version) {
pluginData = {
uniqueIdentifier: plugin.uniqueIdentifier,
version: []// need to update this to be an array
}
}
}
})
I appreciate all the help.
you need to use Array.reduce method:
const data =
[ { uniqueIdentifier: 'theme_test', version: '2011120800' }
, { uniqueIdentifier: 'theme_test', version: '3011120800' }
, { uniqueIdentifier: 'theme_test', version: '4011120800' }
]
const result = Object.values(data.reduce( (r,{uniqueIdentifier,version}) =>
{
r[uniqueIdentifier] ??= { uniqueIdentifier, version:[] }
r[uniqueIdentifier].version.push(version)
return r
},{}))
console.log(result)
Assuming you only have one pluginData: move the new object out of the loop so that it doesn't get created repeatedly, and in the loop push the version to the existing array.
pluginData = {
uniqueIdentifier: plugin.uniqueIdentifier,
version: []
}
item.pluginVersions.items.forEach(function(plugin) {
...
if (plugin.version == supportedPlugin.version) {
pluginData.version.push(plugin.version);
You may also use Array#reduce() and Object.entries() as follows:
const data = [{"uniqueIdentifier": "theme_test","version": "2011120800"},{"uniqueIdentifier": "theme_test","version": "3011120800"},{"uniqueIdentifier": "theme_test","version": "4011120800"}];
const groupedData = Object.entries(
data.reduce(
(prev, {uniqueIdentifier,version}) =>
({ ...prev, [uniqueIdentifier]:(prev[uniqueIdentifier] || []).concat(version) }), {}
)
)
.map(([uniqueIdentifier,version]) => ({uniqueIdentifier,version}));
console.log( groupedData );

Javascript conditionally adding the nested object using map() operator

I have a below JSON,
var original = {
"todos": [
{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [
{
"vpa": "log#bda",
"mccCode": "0000"
}
]
}
]
}
And am trying to add new data inside the nested array i.e., "vpainfo". I have tried using the below code and able to adding the new values inside "vpainfo".
var newdata = {"vpa":"first#bda","mccCode":"1111"};
var newObj =
Object.assign({}, original,
{
todos: original.todos.map(todoInfo=>(todoInfo.accountNo=="50190000")?[
...todoInfo.vpainfo,
newdata
]: todoInfo)
});
And the resulted object is,
{"todos":[[{"vpa":"log#bda","mccCode":"0000"},{"vpa":"first#bda","mccCode":"1111"}]]}
But few of the key and values(accountNo and name) are getting missed, how do we get the full object with the latest updated values?
You only return the array, not the actual object, hence the error.
var original = {
"todos": [
{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [
{
"vpa": "log#bda",
"mccCode": "0000"
}
]
}
]
}
const newdata = {"vpa":"first#bda","mccCode":"1111"};
const newObj = Object.assign({}, original,
{
todos: original.todos.map(todoInfo=>{
if(todoInfo.accountNo=="50190000"){
return {
...todoInfo,
vpainfo: [...todoInfo.vpainfo, newdata]
}
}
return todoInfo
})
});
console.log(newObj)
All those spread operators seem a little excessive...
If all you wanna do is add newdata to that existing array, then do that:
var original = {
"todos": [{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [{
"vpa": "log#bda",
"mccCode": "0000"
}]
}]
};
const newdata = {
"vpa": "first#bda",
"mccCode": "1111"
};
// Find the correct account.
const account = original.todos.filter(t => t.accountNo === '50190000')[0];
if (account) {
account.vpainfo.push(newdata);
}
console.log(original);

Looking for a way to merge Javascript Object keys inside array, only on matching Ids. Map? flatmap?

Looking for a way to merge Javascript Object keys inside array, only on matching Ids. Should i use Map? or flatmap?
I have
const districtList =[
{ id:'1234blah', companyId:'09871345', districtName:'abc1' },
{ id:'2341blah', companyId:'87134590', districtName:'abc2' },
{ id:'3412blah', companyId:'09134587', districtName:'abc3' },
]
and
const companyList =[
{id:'09871345', companyName:'CompanyOne', info:'some' },
{id:'87134590', companyName:'CompanyTwo', info:'stuff' },
{id:'09134587', companyName:'CompanyThree', info:'todo' },
]
But what i want is the data from the company array inside the district array, to get the missing company name, and other info.
const improvedDistrictList =[
{ id:'1234blah', companyId:'09871345', districtName:'abc1', companyName:'CompanyOne', info:'some' },
{ id:'2341blah', companyId:'87134590', districtName:'abc2', companyName:'CompanyTwo', info:'stuff' },
{ id:'3412blah', companyId:'09134587', districtName:'abc3', companyName:'CompanyThree', info:'todo' },
]
I would map through the district list, find a corresponding company for each one based on the companyId and then just add more fields to the new array with one caveat: it looks like your companyList array may or may not contain companyName. As such:
const districtList =[
{id:'1234blah',companyId:'09871345', districtName:'abc1'},
{id:'2341blah',companyId:'87134590', districtName:'abc2'},
{id:'3412blah',companyId:'09134587', districtName:'abc3'},
]
const companyList =[
{id:'09871345',companyName:'CompanyOne', info:'some'},
{id:'87134590',companyId:'CompanyTwo', info:'stuff'},
{id:'09134587',companyId:'CompanyThree', info:'todo'},
]
const result = districtList.map(item => {
const company = companyList.find(c => c.id === item.companyId);
return {...item, [company.companyName ? 'companyName' : 'companyId']: company.companyName ? company.companyName : company.companyId, info: company.info }
})
console.log(result)
Also, as pointed out in the comments, you won't end up with 2 companyId keys in the resulting array as the latter will override the former.
this way...
const districtList =[
{ id:'1234blah', companyId:'09871345', districtName:'abc1' },
{ id:'2341blah', companyId:'87134590', districtName:'abc2' },
{ id:'3412blah', companyId:'09134587', districtName:'abc3' },
]
const companyList =[
{id:'09871345', companyName:'CompanyOne', info:'some' },
{id:'87134590', companyName:'CompanyTwo', info:'stuff' },
{id:'09134587', companyName:'CompanyThree', info:'todo' },
]
const improvedDistrictList = companyList.map(cl=>
({...cl,...districtList.find(x=>x.companyId===cl.id)}))
console.log( improvedDistrictList )
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to check if a key is exists in JSON Array of Objects

I am having the JSON array of objects like below,
let data = [
{
"node":[
{
"name":"aaaaa",
"count":"2",
}
]
},
{
"client":[
{
"name":"bbbbb",
"count":"2",
}
]
},
{
"ip_address":[
{
"name":"ccccc",
"count":"3",
}
]
},
{
"compute":[
{
"name":"dddd",
"count":"1",
}
]
}
]
let find_key = "ip_address";
Need to check whether the root key is exists or not(for example need to find ip_address is exists or not). without foreach please.
JSFiddle Link : https://jsfiddle.net/b9gxhnko/
Tried the following ways but no luck. Some help would be appreciated. Thanks in advance.
Tried like below, but its not working (always returning false),
console.log(data[0].has(find_key)); // false
console.log(data.has(find_key)); // false
console.log(data[0].hasOwnProperty(find_key)); // false
You can try with array.some():
let exists = data.some(x => x[find_key]);
let data = [
{
"node":[
{
"name":"aaaaa",
"count":"2",
}
]
},
{
"client":[
{
"name":"bbbbb",
"count":"2",
}
]
},
{
"ip_address":[
{
"name":"ccccc",
"count":"3",
}
]
},
{
"compute":[
{
"name":"dddd",
"count":"1",
}
]
}
]
let find_key = "ip_address";
let exists = data.some(x => x[find_key]);
console.log(exists);
You have an array of objects, and _.has() an the in expect as single object. Right now you check if the array has a key called ip_address, which it doesn't. Use Array.some() or lodash's _.some(), and check if each object has the key:
const data = [{"node":[{"name":"aaaaa","count":"2"}]},{"client":[{"name":"bbbbb","count":"2"}]},{"ip_address":[{"name":"ccccc","count":"3"}]},{"compute":[{"name":"dddd","count":"1"}]}]
// vanilla JS
const result1 = data.some(o => 'ip_address' in o)
console.log(result1)
// lodash
const result2 = _.some(data, o => _.has(o, 'ip_address'))
console.log(result1)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

functional way to iterate 3 nested arrays

I have a data structure that looks like this:
{
sections: [
{
pages: [
{
questions: [
],
},
],
},
],
}
There's data in the questions array that I'm trying to get at, and return a final 1 dimensional array at the end. There can be an x number of sections, each section can have an x number of pages, and each page can have an x number of questions.
I'm trying to keep the code relatively concise but also readable, this is my current implementation:
function generateQuestionData(survey) {
let data = [];
survey.sections.forEach((section) => {
section.pages.forEach((page) => {
const newData = page.questions.map(getQuestionDataItem);
data = [...data, ...newData];
});
});
return data;
}
EDIT
Is there a way to accomplish the same thing without the data variable reassignment? so something along the lines of
function generateQuestionData(survey) {
return survey.sections.forEach((section) => { // something instead of forEach
section.pages.forEach((page) => page.questions.map(getQuestionDataItem));
// data = [...data, ...newData]; no need for this?
});
}
if that makes sense
How about having a helper for iteration:
function* goOver(array, key, ...keys) {
for(const el of array) {
if(keys.length) {
yield* goOver(el[key] || [], ...keys);
} else {
yield el[key];
}
}
That can be used as:
const result = [...goOver(survey.sections, "pages", "questions")]
.map(getQuestionDataItem);
concerning the second question:
Is there a way to accomplish the same thing without the data variable reassignment?
how about:
data.push(...newData);
You could use reduce in order to show the intent to really do something per section and page to the likes of:
private generateQuestionData = (survey) =>
survey.sections.reduce((data, section) =>
[
...data,
...section.pages.reduce((pageData, page) =>
[
...pageData,
...page.questions.map(getQuestionDataItem)
],
[]
)
],
[]
);
Code indentation/formatting could surely be optimized.
const data = {
sections: [
{
pages: [
{
questions: [
"hello",
"world"
],
},
{
questions: [
"foo",
"bar"
]
}
],
},
],
};
const get = (...pathKeys) => o => pathKeys.reduce((o,k ) => o[k], o);
const flatten = (arrays) => [].concat.apply([], arrays);
const result = flatten(get("sections")(data).map(s => get("pages")(s).map(get("questions"))));
console.log(flatten(flatten(result)));
Note that the flatten at the end could be simplified with a flattenDeep function.
In "pseudo code" I would express your problem like that, with
compose being composition left to right, and map being fn => arr => arr.map(fn)
compose(
get("section"),
map(compose(get("pages"), map(get("questions")))),
flattenDeep,
);

Categories