How to merge map result in to one array objects? - javascript

The object result restructuring function works fine at the same time the map result not coming in one array group.
console.clear();
const filterList = {
ageRange: ["ageRange", "picAgeRange"],
goal: ["goal", "motivation"],
hairColor: ["hairColor", "picHairColor"]
};
const questionList = [{
question: "ageRange",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "18-30",
selected: true
},
{
value: "31-35",
selected: false
},
{
value: "36-45",
selected: false
},
{
value: "46-55",
selected: false
},
{
value: "55+",
selected: false
}
]
},
{
question: "picAgeRange",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "country 6",
selected: true
},
{
value: "smart casual 4",
selected: false
},
{
value: "dark denim 6",
selected: false
},
{
value: "sporty 6",
selected: false
},
{
value: "adventure 5",
selected: false
},
{
value: "prints 5",
selected: false
},
{
value: "excentric 5",
selected: false
},
{
value: "dont like any private style",
selected: false
}
]
},
{
question: "goal",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "save time",
selected: true
},
{
value: "personal advice",
selected: false
},
{
value: "inspiration",
selected: false
},
{
value: "testing the service",
selected: false
}
]
},
{
question: "hairColor",
lastUpdated: "2018-07-09T18:13:49.567",
info: null,
type: "SELECT",
answers: [{
value: "blond",
selected: true
},
{
value: "brown",
selected: false
},
{
value: "black",
selected: false
},
{
value: "red",
selected: false
},
{
value: "grey",
selected: false
},
{
value: "noHair",
selected: false
}
]
},
{
question: "picHairColor",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "suit 3",
selected: true
},
{
value: "business casual",
selected: false
},
{
value: "casual",
selected: false
},
{
value: "have to wear uniform",
selected: false
},
{
value: "classic",
selected: false
},
{
value: "conservative",
selected: false
},
{
value: "relaxed 2",
selected: false
},
{
value: "dont like any work style",
selected: false
}
]
}
];
const ofQuestionsList = Object.entries(filterList).map(
([questionKey, questionNames]) => {
return {
[questionKey]: questionList.filter((item) =>
questionNames.includes(item.question)
)
};
}
);
console.log(ofQuestionsList);
The existing result is
[
{
"ageRange": [
{
"question": "ageRange",
"lastUpdated": "2018-07-09T18:13:42.541",
"info": null,
"type": "SELECT"
},
{
"question": "picAgeRange",
"lastUpdated": "2018-07-09T18:13:42.541",
"info": null,
"type": "SELECT"
}
]
},
{
"goal": [
{
"question": "goal",
"lastUpdated": "2018-07-09T18:13:42.541",
"info": null,
"type": "SELECT"
}
]
},
{
"hairColor": [
{
"question": "hairColor",
"lastUpdated": "2018-07-09T18:13:49.567",
"info": null,
"type": "SELECT"
},
{
"question": "picHairColor",
"lastUpdated": "2018-07-09T18:13:42.541",
"info": null,
"type": "SELECT"
}
]
}
]
The expecting result is
{
"ageRange":[
{
"question":"ageRange",
"lastUpdated":"2018-07-09T18:13:42.541",
"info":null,
"type":"SELECT"
},
{
"question":"picAgeRange",
"lastUpdated":"2018-07-09T18:13:42.541",
"info":null,
"type":"SELECT"
}
],
"goal":[
{
"question":"goal",
"lastUpdated":"2018-07-09T18:13:42.541",
"info":null,
"type":"SELECT"
}
],
"hairColor":[
{
"question":"hairColor",
"lastUpdated":"2018-07-09T18:13:49.567",
"info":null,
"type":"SELECT"
},
{
"question":"picHairColor",
"lastUpdated":"2018-07-09T18:13:42.541",
"info":null,
"type":"SELECT"
}
]
}

Array.prototype.map() returns an array, for your case if I understood correctly you want to group your elements and return them in one results object.
This seems like something that can be achieved with Array.prototype.reduce(), so you would have:
const ofQuestionsList = Object.entries(filterList).reduce(
(acc, [questionKey, questionNames]) => {
return {
...acc,
[questionKey]: questionList.filter((item) =>
questionNames.includes(item.question)
)
};
}, {});
This reduce takes 2 parameters, a callback taking the accumulator and your current element that being processed in your array. And the accumulator's initialization with an empty object {}.
Then in each iteration we return a merged object with the previous values of the iterator, and the current one
console.clear();
const filterList = {
ageRange: ["ageRange", "picAgeRange"],
goal: ["goal", "motivation"],
hairColor: ["hairColor", "picHairColor"]
};
const questionList = [{
question: "ageRange",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "18-30",
selected: true
},
{
value: "31-35",
selected: false
},
{
value: "36-45",
selected: false
},
{
value: "46-55",
selected: false
},
{
value: "55+",
selected: false
}
]
},
{
question: "picAgeRange",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "country 6",
selected: true
},
{
value: "smart casual 4",
selected: false
},
{
value: "dark denim 6",
selected: false
},
{
value: "sporty 6",
selected: false
},
{
value: "adventure 5",
selected: false
},
{
value: "prints 5",
selected: false
},
{
value: "excentric 5",
selected: false
},
{
value: "dont like any private style",
selected: false
}
]
},
{
question: "goal",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "save time",
selected: true
},
{
value: "personal advice",
selected: false
},
{
value: "inspiration",
selected: false
},
{
value: "testing the service",
selected: false
}
]
},
{
question: "hairColor",
lastUpdated: "2018-07-09T18:13:49.567",
info: null,
type: "SELECT",
answers: [{
value: "blond",
selected: true
},
{
value: "brown",
selected: false
},
{
value: "black",
selected: false
},
{
value: "red",
selected: false
},
{
value: "grey",
selected: false
},
{
value: "noHair",
selected: false
}
]
},
{
question: "picHairColor",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT",
answers: [{
value: "suit 3",
selected: true
},
{
value: "business casual",
selected: false
},
{
value: "casual",
selected: false
},
{
value: "have to wear uniform",
selected: false
},
{
value: "classic",
selected: false
},
{
value: "conservative",
selected: false
},
{
value: "relaxed 2",
selected: false
},
{
value: "dont like any work style",
selected: false
}
]
}
];
const ofQuestionsList = Object.entries(filterList).reduce(
(acc, [questionKey, questionNames]) => {
return {
...acc,
[questionKey]: questionList.filter((item) =>
questionNames.includes(item.question)
)
};
}, {});
console.log(ofQuestionsList);

Manage with result
console.clear();
const result = [{
ageRange: [{
question: "ageRange",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT"
},
{
question: "picAgeRange",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT"
}
]
},
{
goal: [{
question: "goal",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT"
}]
},
{
hairColor: [{
question: "hairColor",
lastUpdated: "2018-07-09T18:13:49.567",
info: null,
type: "SELECT"
},
{
question: "picHairColor",
lastUpdated: "2018-07-09T18:13:42.541",
info: null,
type: "SELECT"
}
]
}
];
var newObj = result.reduce((a, b) => Object.assign(a, b), {})
console.log(newObj)

Related

Nested filtering of 2D array doesn't work as expected

I have a 2D array where the outer array contains objects, each of which contains another array of objects. Here is the data:
const companies = [{
companyId: 100,
companyName: "Company 1",
transactions: [
{ id: "10421", date: "09/19/2022", selected: true, },
{ id: "00467", date: "05/08/2022", selected: true, },
],
},
{
companyId: 200,
companyName: "Company 2",
transactions: [
{ id: "259A6", date: "01/11/2022", selected: false, },
{ id: "87K37", date: "04/14/2022", selected: false, },
],
},
];
I want to get the list of transactions that have their selected fields set to true. This is how I am filtering the data:
const selectedTransactions = companies.filter((c) =>
c.transactions.filter((t) => t.selected === true));
Instead of getting the transactions of only the first company, I'm getting the transactions of ALL companies, including the ones that are not selected. Am I making a mistake somewhere?
You could flat-map the overall companies; then internally filter and map the transaction IDs and dates along with the company ID.
const companies = [{
companyId: 100,
companyName: "Company 1",
transactions: [
{ id: "10421", date: "09/19/2022", selected: true },
{ id: "00467", date: "05/08/2022", selected: true },
],
}, {
companyId: 200,
companyName: "Company 2",
transactions: [
{ id: "259A6", date: "01/11/2022", selected: false },
{ id: "87K37", date: "04/14/2022", selected: false },
],
}];
const selected = companies
.flatMap(({ companyId, transactions }) => transactions
.filter(({ selected }) => selected)
.map(({ id: transactionId, date: transactionDate }) =>
({ companyId, transactionId, transactionDate })));
console.log(selected);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Result
[
{ "companyId": 100, "transactionId": "10421", "transactionDate": "09/19/2022" },
{ "companyId": 100, "transactionId": "00467", "transactionDate": "05/08/2022" }
]
If youre just looking for the transactions you could use map, though it does return a second empty array. Or just add a little to your filter function to get only the company with what youre looking for.
const companies = [{
companyId: 100,
companyName: "Company 1",
transactions: [
{ id: "10421", date: "09/19/2022", selected: true },
{ id: "00467", date: "05/08/2022", selected: true },
],
}, {
companyId: 200,
companyName: "Company 2",
transactions: [
{ id: "259A6", date: "01/11/2022", selected: false },
{ id: "87K37", date: "04/14/2022", selected: false },
],
}];
// USING MAP TO GET TRANSACTIONS
const st = companies.map(c => c.transactions.filter(t => t.selected === true))
console.log(st);
// USING FILTER TO GET COMPANY
const selectedTransactions = companies.filter(c => {
c.transactions = c.transactions.filter(t => t.selected === true);
if (c.transactions.length) return c;
});
console.log(selectedTransactions);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Result
1
[
[
{
"id": "10421",
"date": "09/19/2022",
"selected": true
},
{
"id": "00467",
"date": "05/08/2022",
"selected": true
}
],
[]
]
2
[
{
"companyId": 100,
"companyName": "Company 1",
"transactions": [
{
"id": "10421",
"date": "09/19/2022",
"selected": true
},
{
"id": "00467",
"date": "05/08/2022",
"selected": true
}
]
}
]

How to use conditional statement for sort in Mongodb

let me illustrate with an example,
suppose my collection is like this,
products = [
{
id: 1,
name: "a",
offer: true,
expiryDate: "23-03-2022"
},
{
id: 2,
name: "b",
offer: false,//no offer
},
{
id: 3,
name: "c",
offer: true,
expiryDate: "01-01-2021"//already expired
},
{
id: 4,
name: "d",
offer: true,
expiryDate: "01-06-2022"
},
]
I want here, the offered items comes first in descending order,
it should not expire and then the remaining item should come in
descending order so result would be like this
[
{
id: 4,
name: "d",
offer: true,
expiryDate: "01-06-2022"
},
{
id: 1,
name: "a",
offer: true,
expiryDate: "23-03-2022"
},
{
id: 3,
name: "c",
offer: true,
expiryDate: "01-01-2021"
},
{
id: 2,
name: "b",
offer: false,
},
]
db.collection.aggregate([
{
"$match": {}
},
{
"$set": {
"offer": {
"$cond": {
"if": {
"$lt": [
{
"$toDate": "$expiryDate"
},
"$$NOW"
]
},
"then": false,
"else": true
}
},
"expiryDate": {
"$toDate": "$expiryDate"
}
}
},
{
"$sort": {
"expiryDate": -1,
"offer": -1
}
}
])
mongoplayground

How to segregate an array of object by using map?

I have to form an array of object in another array of object based on id. I was able to group the object based the "applicationId" but was not able to group the inside array of attributes and values array. Also the above code gives me duplicate objects. Please help with this I know its a small fix but I spend whole day still no result.stackblitz. Expected output commented below in stackblitz
data.map((el) => {
el.attribute.map((elm) => {
elm.options.map(em => {
permissions.push({
applicationId: el.application, attributes: [{ name: elm.name, value: em.value, disabled: true
}]
})
})
})
});
Input Object
[
{
application: "abc",
attribute: [
{
description: "abc description1"
name: "audio"
options:[
{name: "Yes", value: "Y"}
{name: "No", value: "N"}
]
},
{
description: "abc description2"
name: "video"
options:[
{name: "true", value: "T"}
{name: "false", value: "F"}
]
}
{
description: "abc description3"
name: "call"
options:[
{name: "Yes", value: "Y"}
{name: "false", value: "F"}
]
}
]
},
{
application: "def",
attribute: [
{
description: "def description1"
name: "audio"
options:[
{name: "Yes", value: "Y"}
{name: "No", value: "N"}
]
},
{
description: "def description2"
name: "video"
options:[
{name: "true", value: "T"}
{name: "false", value: "F"}
]
}
{
description: "def description3"
name: "call"
options:[
{name: "Yes", value: "Y"}
{name: "false", value: "F"}
]
}
]
}
]
Expected Output:
permissions:[
{
applicationId:abc
attributes:
[
{
name:audio
value:["Y","N"]
disabled: true
},
{
name:video,
value:["T","F"]
disabled: true
},
{
name:call,
value:["Y","F"]
disabled: true
}
]
},
{
applicationId: def
attributes:
[
{
name:audio
value:["Y","N"]
disabled: true
},
{
name:video,
value:["T","F"]
disabled: true
},
{
name:call,
value:["Y","F"]
disabled: true
}
]
}
]
You could do so using few array maps.
Try the following
var input = [ { application: "abc", attribute: [ { description: "abc description1", name: "audio", options: [ { name: "Yes", value: "Y" }, { name: "No", value: "N" } ] }, { description: "abc description2", name: "video", options: [ { name: "true", value: "T" }, { name: "false", value: "F" } ] }, { description: "abc description3", name: "call", options: [ { name: "Yes", value: "Y" }, { name: "false", value: "F" } ] } ] }, { application: "def", attribute: [ { description: "def description1", name: "audio", options: [ { name: "Yes", value: "Y" }, { name: "No", value: "N" } ] }, { description: "def description2", name: "video", options: [ { name: "true", value: "T" }, { name: "false", value: "F" } ] }, { description: "def description3", name: "call", options: [ { name: "Yes", value: "Y" }, { name: "false", value: "F" } ] } ] } ];
var output = input.map(item => ({
applicationId: item.application,
attributes: item.attribute.map(attr => ({
name: attr.name,
value: attr.options.map(option => option.value),
disabled: true
}))
}));
console.log(output);
I've modified your Stackblitz.
Sidenote: Please try to post a valid object in the question. It'll make it much easier and quicker to reproduce the issue. Much of my time was spent not in the solution but in fixing the object.

How to change property value in array object with array values in javascript

How to change property in the object array based on array of values in javascript,
I have object obj and parameter as list, should changed the property checked to true, if title matched with the list in javascript
if the title is matched with list and has children, then checked: true
ie.countries title is matched with list , then children also change the property checked: true
if the children title is matched , then change checked: true for that object only
ie.clothes title is matched with list , then change the property checked: true for that object only
I stuck to do with list of arrays as param,
var obj = [{
title: "Sample",
checked: false,
children: [{
title: "products",
checked: false,
children: [{
title: "clothes",
id: 1,
checked: false
},
{
title: "electronics",
id: 2,
checked: false
}
]
},
{
title: "countries",
checked: false,
children: [{
title: "IN",
id: 1,
checked: false
},
{
title: "TH",
id: 2,
checked: false
}
]
}
]
}];
var list = ["clothes", "countries"];
Expected Output:
[{
title: "Sample",
checked: false,
children: [
{
title: "products",
checked: false,
children: [
{title: "clothes", id: 1, checked: true},
{title: "electronics", id: 2, checked: false}
]
},{
title: "countries",
checked: true,
children: [
{title: "IN", id: 1, checked: true},
{title: "TH", id: 2, checked: true}
]
}
]
}]
You need some recursion, to handle any depth of nesting:
With this solution, it is very generic, you can change the childrenProp, matchProp, checkedProp etc. and it will allow you to search as deep as you need to in a nested structure.
const obj = [
{
title: "Sample",
checked: false,
children: [
{
title: "products",
checked: false,
children: [
{title: "clothes", id: 1, checked: false},
{title: "electronics", id: 2, checked: false}
]
},
{
title: "countries",
checked: false,
children: [
{title: "IN", id: 1, checked: false},
{title: "TH", id: 2, checked: false}
]
}
]
}
];
var list=["clothes", "countries"];
checkPropertyForMatch(obj, list);
console.log(obj);
checkPropertyForMatch(obj, ['electronics']);
console.log(obj);
function checkPropertyForMatch(inputArr, matchList, matchProp, childrenProp, checkedProp){
//default params, or they can be overwritten:
matchProp = matchProp || 'title';
childrenProp = childrenProp || 'children';
checkedProp = checkedProp || 'checked';
innerRecursive(inputArr, matchList);
//recursively search the nested object:
function innerRecursive(currArr, list){
for (item of currArr){
if ( list.includes(item[matchProp]) ){
item[checkedProp] = true;
if (item[childrenProp]){
//this parent matched, so mark all children as marked too:
markAllChildrenChecked(item[childrenProp]);
}
}
else {
item[checkedProp] = false;
if (item[childrenProp]) {
//it didn't match but it has children, so search them too:
innerRecursive(item[childrenProp], list)
}
}
}
}
//this recursively marks all children as checked = true:
function markAllChildrenChecked(currArr){
for (item of currArr){
item[checkedProp] = true;
if (item[childrenProp]){
markAllChildrenChecked(item[childrenProp]);
}
}
}
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Output:
[
{
"title": "Sample",
"checked": false,
"children": [
{
"title": "products",
"checked": false,
"children": [
{"title": "clothes", "id": 1, "checked": true},
{"title": "electronics", "id": 2, "checked": false}
]
},
{
"title": "countries",
"checked": true,
"children": [
{"title": "IN", "id": 1, "checked": true},
{"title": "TH", "id": 2, "checked": true}
]
}
]
}
]
The trick here is below:
if (list.indexOf(ele.title) > -1 || list.indexOf(el.title) > -1) {
el.checked = true;
}
var obj = [{
title: "Sample",
checked: false,
children: [{
title: "products",
checked: false,
children: [{
title: "clothes",
id: 1,
checked: false
},
{
title: "electronics",
id: 2,
checked: false
}
]
},
{
title: "countries",
checked: false,
children: [{
title: "IN",
id: 1,
checked: false
},
{
title: "TH",
id: 2,
checked: false
}
]
}
]
}];
var list = ["clothes", "countries"];
obj.forEach(elem => {
elem.children.forEach(ele => {
ele.children.forEach(el => {
if (list.indexOf(ele.title) > -1 || list.indexOf(el.title) > -1) {
el.checked = true;
}
})
})
})
console.log(obj)

Javascript console error elem.find() is not a function

I am working on learning to make jQuery plugins and made the following plugin, forgive me for the wall of code:
$.fn.addressForm = function () {
return this.each(function () {
var elem = $(this);
$.each(elem.find(".addr-country select"), function ( elem ) {
$(this).on('change', function (elem ) {
// var elem = $(this).parents(".form-address");
if ($(this).val() === "US") {
elem.find(".addr-state label").html("State"); // eror gets thrown about this line
elem.find(".addr-postal-code label").html("Zip");
elem.find(".addr-street-1").show();
elem.find(".addr-street-2").show();
elem.find(".addr-city").show();
elem.find(".addr-state").show();
elem.find(".addr-postal-code").show();
var states = [
{ text: "AL", value: "AL" },
{ text: "AK", value: "AK" },
{ text: "AZ", value: "AZ" },
{ text: "AR", value: "AR" },
{ text: "CA", value: "CA" },
{ text: "CO", value: "CO" },
{ text: "CT", value: "CT" },
{ text: "DE", value: "DE" },
{ text: "FL", value: "FL" },
{ text: "GA", value: "GA" },
{ text: "HI", value: "HI" },
{ text: "ID", value: "ID" },
{ text: "IL", value: "IL" },
{ text: "IN", value: "IN" },
{ text: "IA", value: "IA" },
{ text: "KS", value: "KS" },
{ text: "KY", value: "KY" },
{ text: "LA", value: "LA" },
{ text: "ME", value: "ME" },
{ text: "MD", value: "MD" },
{ text: "MA", value: "MA" },
{ text: "MI", value: "MI" },
{ text: "MN", value: "MN" },
{ text: "MS", value: "MS" },
{ text: "MO", value: "MO" },
{ text: "MT", value: "MT" },
{ text: "NE", value: "NE" },
{ text: "NV", value: "NV" },
{ text: "NH", value: "NH" },
{ text: "NJ", value: "NJ" },
{ text: "NM", value: "NM" },
{ text: "NY", value: "NY" },
{ text: "NC", value: "NC" },
{ text: "ND", value: "ND" },
{ text: "OH", value: "OH" },
{ text: "OK", value: "OK" },
{ text: "OR", value: "OR" },
{ text: "PA", value: "PA" },
{ text: "RI", value: "RI" },
{ text: "SC", value: "SC" },
{ text: "SD", value: "SD" },
{ text: "TN", value: "TN" },
{ text: "TX", value: "TX" },
{ text: "UT", value: "UT" },
{ text: "VT", value: "CT" },
{ text: "VA", value: "VA" },
{ text: "WA", value: "WA" },
{ text: "WV", value: "WV" },
{ text: "WI", value: "WI" },
{ text: "WY", value: "WY" },
{ text: "D.C.", value: "D.C." }
];
elem.find(".addr-state select").empty();
$.each(states, function (index, value) {
var o = new Option(value.text, value.value);
$(o).html(value.text);
elem.find(".addr-state select").append(o);
});
}
if ($(this).val() === "CA") {
// Update labels
elem.find(".addr-state label").html("Province");
elem.find(".addr-postal-code label").html("Postal Code");
// Show fields
elem.find(".addr-street-1").show();
elem.find(".addr-street-2").show();
elem.find(".addr-city").show();
elem.find(".addr-state").show();
elem.find(".addr-postal-code").show();
var states = [
{ text: "AB", value: "AB" },
{ text: "BC", value: "BC" },
{ text: "MB", value: "MB" },
{ text: "NB", value: "NB" },
{ text: "NL", value: "NL" },
{ text: "NS", value: "NS" },
{ text: "ON", value: "ON" },
{ text: "PE", value: "PE" },
{ text: "QC", value: "QC" },
{ text: "SK", value: "SK" },
{ text: "NT", value: "NT" },
{ text: "NU", value: "NU" },
{ text: "YT", value: "YT" }
];
// Reset state options
elem.find(".addr-state select").empty();
$.each(states, function (index, value) {
var o = new Option(value.text, value.value);
$(o).html(value.text);
elem.find(".addr-state select").append(o);
});
}
})
});
})
}
For some reason passing in elem to the on change function is not getting recognized. If I were to un-comment the line that says var elem = $(this).parents(".form-address"); it works fine. But I need the $(this) instance of the original selected element to be used, not a specific class. What am I doing wrong?

Categories

Resources