I have an array of objects:
const guests = [
{ id: 1, rsvp: true },
{ id: 2, rsvp: false },
{ id: 3, rsvp: true },
{ id: 4, rsvp: false }
];
I would like to write a function which selects only the objects corresponding to IDs (guests) who have rsvp'd.
function selectGuests(guests, id) {
list.forEach(function(id) {
if(id.true) {
push.SelectGuests();
}
});
return selectGuests;
}
however, I am getting gibberish results.
Any help on this one or points in the right direction would be appreciated!
Cheers!
Use array.filter()
DEMO
const guests = [
{ id: 1, rsvp: true },
{ id: 2, rsvp: false },
{ id: 3, rsvp: true },
{ id: 4, rsvp: false }
];
var result = guests.filter(t=>t.rsvp);
console.log(result);
using forEach
function selectGuests(guests)
{
let result = [];
guests.forEach(function (guest) {
if (guest.rsvp) {
result.push(guest);
}
});
return result;
}
const guests = [
{ id: 1, rsvp: true },
{ id: 2, rsvp: false },
{ id: 3, rsvp: true },
{ id: 4, rsvp: false }
];
let a = selectGuests(guests);
console.log(a);
or simpler using filter method
const guests = [
{ id: 1, rsvp: true },
{ id: 2, rsvp: false },
{ id: 3, rsvp: true },
{ id: 4, rsvp: false }
];
let a = guests.filter(function(item){return item.rsvp});
console.log(a);
here is a simplified version without using es6 features.
function selectGuests(guests) {
var selectedGuests = []
// forEach gets the array elements (one by one) as first param
guests.forEach(function(guest) {
if(guest.rsvp) {
selectedGuests.push(guest)
}
})
return selectedGuests
}
// call it as follows
selectGuests(guests)
Related
I have confusion on recursive function to split recursive array into another recursive arrays. Let say I have an item and inside it there is packaged items (or children), and the children also have an item and children, there's no limitation about the recursion level.
The problem
I need to separate the paths of package item object that has isOptional true and paths of isOptional false. The function should return 2 categorized array and the value inside the array must be recursive just like the input structure. Please check the diagram below
Here's input example
const product = {
name: "Product 1",
packagedItems: [
{
id: 1,
isOptional: false,
item: {
name: "1#1",
packagedItems: [
{
id: 3,
isOptional: false,
item: {
name: "2#1",
packagedItems: [
{
id: 5,
isOptional: false,
item: {
name: "3#1",
packagedItems: []
}
},
{
id: 6,
isOptional: true,
item: {
name: "3#2",
packagedItems: []
}
}
]
}
}
]
}
},
{
id: 2,
isOptional: false,
item: {
name: "1#2",
packagedItems: [
{
id: 4,
isOptional: false,
item: {
name: "2#2",
packagedItems: [
{
id: 7,
isOptional: true,
item: {
name: "3#3",
packagedItems: []
}
},
{
id: 8,
isOptional: true,
item: {
name: "3#4",
packagedItems: []
}
}
]
}
}
]
}
}
]
};
Here's the diagram
enter image description here
What I've tried is only able to get parent's name but not building the same structure as the input
const getParents = (
packagedItems: PackagedItem[],
ancestors: (string | PackagedItem)[] = []
): any => {
for (let pack of packagedItems) {
if (pack.isOptional && !pack.item.packagedItems.length) {
return ancestors.concat(pack);
}
const found = getParents(
pack.item.packagedItems,
ancestors.concat(pack.item.name)
);
if (found) {
return found;
}
}
return undefined;
};
console.log(getParents(product.packagedItems));
only return
[
"1#1",
"2#1",
{
id: 6
isOptional: true
item: Object
}
]
Expected result would be two arrays like this.
const optionalTrue = [
{
id: 1,
isOptional: false,
item: {
name: "1#1",
packagedItems: [
{
id: 3,
isOptional: false,
item: {
name: "2#1",
packagedItems: [
{
id: 6,
isOptional: true,
item: {
name: "3#2",
packagedItems: []
}
}
]
}
}
]
}
},
{
id: 2,
isOptional: false,
item: {
name: "1#2",
packagedItems: [
{
id: 4,
isOptional: false,
item: {
name: "2#2",
packagedItems: [
{
id: 7,
isOptional: true,
item: {
name: "3#3",
packagedItems: []
}
},
{
id: 8,
isOptional: true,
item: {
name: "3#4",
packagedItems: []
}
}
]
}
}
]
}
}
];
const optionalFalse = [
{
id: 1,
isOptional: false,
item: {
name: "1#1",
packagedItems: [
{
id: 3,
isOptional: false,
item: {
name: "2#1",
packagedItems: [
{
id: 5,
isOptional: false,
item: {
name: "3#1",
packagedItems: []
}
}
]
}
}
]
}
}
];
Your function is going in the right direction, but the pack is a leaf, and matches the category, you should not continue with the recursive call. Also the collection into the ancestors array will not work well as you collect either pack or name in it.
Here is an implementation that gives the output you intended:
function filterOnLeaf(item, optional) {
return {
...item,
packagedItems: item.packagedItems.map(package => {
if (!package.item.packagedItems.length) { // Leaf
if (package.isOptional != optional) return null;
} else { // Internal
package = {
...package,
item: filterOnLeaf(package.item, optional)
};
if (!package.item.packagedItems.length) return null;
}
return package;
}).filter(Boolean)
};
}
const product = {name: "Product 1",packagedItems: [{id: 1,isOptional: false,item: {name: "1#1",packagedItems: [{id: 3,isOptional: false,item: {name: "2#1",packagedItems: [{id: 5,isOptional: false,item: {name: "3#1",packagedItems: []}},{id: 6,isOptional: true,item: {name: "3#2",packagedItems: []}}]}}]}},{id: 2,isOptional: false,item: {name: "1#2",packagedItems: [{id: 4,isOptional: false,item: {name: "2#2",packagedItems: [{id: 7,isOptional: true,item: {name: "3#3",packagedItems: []}},{id: 8,isOptional: true,item: {name: "3#4",packagedItems: []}}]}}]}}]};
const optionalTrue = filterOnLeaf(product, true);
const optionalFalse = filterOnLeaf(product, false);
console.log("optional is true:");
console.log(optionalTrue);
console.log("optional is false:");
console.log(optionalFalse);
I've got an array of objects. I want to be able to group objects in parent's object , parent object is determined by broker: true. Is there a way to convert this:
const data = [
{ id: 1, broker: true },
{ id: 2, broker: false },
{ id: 3, broker: false },
{ id: 4, broker: true },
{ id: 5, broker: false },
{ id: 6, broker: true },
{ id: 7, broker: false },
{ id: 8, broker: false },
{ id: 9, broker: false },
];
Into something like this:
const data = [
{ id: 1, broker: true, chunks: [
{ id: 2, broker: false },
{ id: 3, broker: false },
]},
{ id: 4, broker: true, chunks: [
{ id: 5, broker: false },
]},
{ id: 6, broker: true, chunks: [
{ id: 7, broker: false },
{ id: 8, broker: false },
{ id: 9, broker: false },
]},
];
You could check the propery for broker and push either a new object to the result set, or push the object to the previous object's chunks array.
const
data = [{ id: 1, broker: true }, { id: 2, broker: false }, { id: 3, broker: false }, { id: 4, broker: true }, { id: 5, broker: false }, { id: 6, broker: true }, { id: 7, broker: false }, { id: 8, broker: false }, { id: 9, broker: false }],
grouped = data.reduce((r, o) => {
if (o.broker) {
r.push(Object.assign({}, o, { chunks: [] }));
} else {
r[r.length - 1].chunks.push(o);
}
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Use reduce to add to an accumulator every time it runs into a true value, and if it runs into a false value, add to the previous object via the property chunks
data.reduce((a, cv) => {
let len = a.length - 1;
return (cv["broker"]) ? (a.push(cv), a) : (a[len]
["chunks"] || (a[len]["chunks"] = []), a[len]
["chunks"].push(cv), a);
}, []);
const data = [
{ id: 1, broker: true },
{ id: 2, broker: false },
{ id: 3, broker: false },
{ id: 4, broker: true },
{ id: 5, broker: false },
{ id: 6, broker: true },
{ id: 7, broker: false },
{ id: 8, broker: false },
{ id: 9, broker: false },
];
let result = data.reduce((a, cv) => {
let len = a.length - 1;
return (cv["broker"]) ? (a.push(cv), a) : (a[len]["chunks"] || (a[len]["chunks"] = []), a[len]["chunks"].push(cv), a);
}, []);
console.log(result);
You have to go through the array, create a new one and evaluate the condition you need, if it is met, put it in the new array
Object.keys(data).forEach((value, index) => {
// code
})
You are going through the keys of each object
Object.keys(data).forEach(key => {
console.log(data[index].property)
})
found
I am filtering array whenever checkboxes are checked. There are totally 7 checkboxe each is associated with an object.
here is my code,
if (this.deliveryConcession[0].checked) {
this.allItems = this.allItems.filter(fil => fil.deliveryconcession.readytoship === this.deliveryConcession[0].checked);
}
if (this.deliveryConcession[1].checked) {
this.allItems = this.allItems.filter(fil => fil.deliveryconcession.instantdownload === this.deliveryConcession[1].checked);
}
if (this.deliveryConcession[2].checked) {
this.allItems = this.allItems.filter(fil => fil.deliveryconcession.unespecifiedshipment === this.deliveryConcession[2].checked);
}
if (this.seatConcession[0].checked) {
this.allItems = this.allItems.filter(fil => fil.seatingConcession.parking === this.seatConcession[0].checked);
}
if (this.seatConcession[1].checked) {
this.allItems = this.allItems.filter(fil => fil.seatingConcession.restrictedview === this.seatConcession[1].checked);
}
if (this.seatConcession[2].checked) {
this.allItems = this.allItems.filter(fil => fil.seatingConcession.wheelchair === this.seatConcession[2].checked);
}
if (this.seatConcession[3].checked) {
this.allItems = this.allItems.filter(fil => fil.seatingConcession.alcoholFree === this.seatConcession[3].checked);
}
here is my objects for filter,
seatConcession = [
{ id: 1, name: 'Parking pass included', checked: false },
{ id: 2, name: 'Unrestricted view', checked: false },
{ id: 3, name: 'Wheel chair accessible', checked: false },
{ id: 4, name: 'Without age restrictions', checked: false }
];
deliveryConcession = [
{ id: 1, name: 'Ready to ship(paper)', checked: false },
{ id: 2, name: 'Instant download(e-ticket)', checked: false },
{ id: 3, name: 'Unspecified shipment(paper)', checked: false }
];
how can i improve the above with simple loadash filter or another way?
let keys = [
["readytoship", "deliveryConcession"],
["instantdownload", "deliveryConcession"],
/* and so on, make sure to order */
];
this.allItems.filter(item => {
return keys.every((arr, i) => {
let [k, attr] = arr;
return item[attr][k] === this[attr][i].checked;
});
});
You will need to order the keys array appropriately. But now it's a two-liner. Other than let and the arrow functions this is all valid ES 5, no lodash required.
EDIT
Since you still haven't actually posted the relevant code this is still something of a stab in the dark, but taking your sample input of
seatConcession = [
{ id: 1, name: 'Parking pass included', checked: false },
{ id: 2, name: 'Unrestricted view', checked: false },
{ id: 3, name: 'Wheel chair accessible', checked: false },
{ id: 4, name: 'Without age restrictions', checked: false }
];
deliveryConcession = [
{ id: 1, name: 'Ready to ship(paper)', checked: false },
{ id: 2, name: 'Instant download(e-ticket)', checked: false },
{ id: 3, name: 'Unspecified shipment(paper)', checked: false }
];
And assuming you have a list of which checkboxes are checked that is ordered in the same order as the objects like so
let checked = [true, false, true, true, false /* etc */];
You want to do something like this:
let filtered = seatConcessions
.concat(deliveryConcession)
.filter((obj, i) => checked[i]);
You will have to adapt this to your specific case (again, since the sample input you put up is different than the code you wrote), but is a pattern for doing this in general.
could you please tell me why my script is broken?
It is an exercise in a Udemy lesson.
You need only returning users who have admin level access
var users = [
{ id: 1, admin: true },
{ id: 2, admin: false },
{ id: 3, admin: false },
{ id: 4, admin: false },
{ id: 5, admin: true },
];
var filteredUsers;
function isAdmin(array, property){
return array.filter(function(key){
return key[property] === 'true';
})
}
filteredUsers = isAdmin(users, 'admin');
Thank you
You need to test against a boolean value, because your data has true or false values.
return key[property] === true;
// ^^^^
function isAdmin(array, property) {
return array.filter(function (key) {
return key[property] === true;
// ^^^^
});
}
var users = [{ id: 1, admin: true }, { id: 2, admin: false }, { id: 3, admin: false }, { id: 4, admin: false }, { id: 5, admin: true }],
filteredUsers = isAdmin(users, 'admin');
console.log(filteredUsers);
)Your problem is that your are using the 3 equal sing ("===") to test the proprety. Here's a link with more details that explains the difference between :
https://stackoverflow.com/a/523650/5235299
I am trying to implement a function "markActive", which, when given a list of objects and an id, returns the same list, but with the corresponding object marked active, like for example,
var list = [
{ id: 1, active: false },
{ id: 2, active: false },
{ id: 3, active: true },
{ id: 4, active: false }
];
when function is called
markActive(list, 2);
should Return:
[
{ id: 1, active: false },
{ id: 2, active: true },
{ id: 3, active: false },
{ id: 4, active: false }
]
i tried many loops but everytime i was getting undefined,
thank you in advance.
You could iterate the array and set active with a check of the id.
function markActive(array, id) {
array.forEach(function (o) {
o.active = o.id === id;
});
return list;
}
var list = [{ id: 1, active: false }, { id: 2, active: false }, { id: 3, active: true }, { id: 4, active: false }];
console.log(markActive(list, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Use Array#forEach
var list = [{
id: 1,
active: false
}, {
id: 2,
active: false
}, {
id: 3,
active: true
}, {
id: 4,
active: false
}];
function markActive(list, id) {
list.forEach(function(el) {
if (el.id == id) {
el.active = true;
} else {
el.active = false;
}
});
}
markActive(list, 2);
console.log(list);
Set everything to inactive unless the id should be set to active then do that
function markActive(list, item) {
list.forEach(function(element) {
if (element.active) {
element.active = false;
}
if (element.id === item) {
console.log(item)
element.active = true;
}
})
}