Can you merge an array of object into just one "big" array? - javascript

I need to filter based on a search of words,
When I look up one word it pulls up what I need, but I've been having some trouble when it comes to seaching for multiple words that meet the requirements.
So the thing is, I need to keep the previous search and add into this array the next results from the second word.
/* ===== Search images by keyword =====*/
searchByKeyword() {
if (this.searchText != "" && this.searchText != null) {
if (this?.plansBeforeSearch?.length == 0) {
this.plansBeforeSearch = this.selectedPlans;
}
this.searchTextDivision();
for (let i = 0; i < this.searchTextArray.length; i++) {
/* this.filteredImages = */
this.test[i] = this.planCollection
.filter(
(pl) =>
this.plansBeforeSearch.find((p) => p.name == pl.name) != null
)
.filter((plan: Plan) => {
return [
plan.id,
plan.code,
plan.name,
plan.gallery,
plan.tags,
plan.brand,
plan.description,
plan.width,
plan.depth,
plan.sqf,
plan.bedrooms,
].some((field) =>
field
?.toString()
?.toLowerCase()
?.includes(
this.searchTextArray[i].toString().toLowerCase().trim()
)
);
});
}
this.filteredImages = this.test[0];
console.log(this.test);
console.log(this.filteredImages);
}
}
I created an array of the words I want to use and for each loop I kept them on this test array. It keeps all images that meet the requirement
But when I pass it to the filteredImages array that is the one that displays the images, I can only pass ONE position. So in the code I shared I set up the first position to show, but I need all three of them!
I thought maybe if I merge all the arrays that the test array has into one array with one position only I can pass that to the filteredImages

Try with flat array:
this.filteredImages = this.test.flat()

Related

Javascript filter with multiple criteria

I am filtering items based off of multiple criteria. in my sample I have three different criteria but the final code will have 5 different criteria. My current code works but it is not efficient and now that I have added a third criteria it is getting blotted. I know there has to be a better more efficient way to write the code.
My three filters are: Search, Year & Weeks.
return this.list.filter((item) =>{
let results
// if search only
if(this.search) {
results = item.title.toLowerCase().match(this.search.toLowerCase())
}
// if a year is selected only
if(this.whichYear) {
results = this.checkForDefaultYear(item).includes(this.whichYear)
}
// if num of weeks only
if(this.numOfWeeks) {
results = item.units.length === this.numOfWeeks
}
// if both search and year
if(this.search && this.whichYear) {
results = this.checkForDefaultYear(item).includes(this.whichYear) && item.title.toLowerCase().match(this.search.toLowerCase())
}
// if neither search or year
if(!this.search && !this.whichYear && !this.numOfWeeks)
results = item.title
return results
})
The below above works but now that I have added Weeks I have to do something like
if(this.search && this.whichYear && this.numOfWeeks) {}
if(this.search && this.whichYear) {}
if(this.search && this.numOfWeeks) {}
if(this.whichYear && this.numOfWeeks) {}
This is going to get out of control once I have all 5 filters. This does not seem like the best way to write this code.
I'm not sure if I understand correctly, but from what I understand you want to run a series of checks together, depending on whether a user selected certain options or not.
To do so, you can try with this approach:
return this.list.filter((item) =>{
let results = !!item.title; // default filter
// if previous filters and search
if(this.search) {
results = results && item.title.toLowerCase().match(this.search.toLowerCase());
}
// if previous filters and year
if(this.whichYear) {
results = results && this.checkForDefaultYear(item).includes(this.whichYear)
}
// if previous filters and weeks
if(this.numOfWeeks) {
results = results && item.units.length === this.numOfWeeks
}
return results;
});
Here, it works like this:
Apply default filter, in this case, the title must be not empty
If a user selected the search filter, you apply an additional condition to the previous ones (here only default)
If a user selected the whichYear filter, you apply an additional condition to the previous ones (here default and search)
If a user selected the numOfWeeks filter, you apply an additional condition to the previous ones (here default, search, and year)
So you basically extend the conditions chain depending on what your user selects. And this way you can add more filters according to your needs.
You could also do a similar thing using arrays: create a filters array and push() a filter with every condition and in the end, check if every filter returned true.
The filter callback needs a true or false value.
So the most common way is to return false if a check fails, end return true if it's correct :
return this.list.filter((item) =>{
if (condition1) {
return false; // Invalid
}
if (condition2) {
return false; // Invalid
}
// Valid
return true;
})
So in your case, you can do somthing like:
return this.list.filter((item) =>{
// if search only
if (item.title.toLowerCase().match(this.search.toLowerCase()) {
return false
}
// if a year is selected only
if (this.checkForDefaultYear(item).includes(this.whichYear)) {
return false
}
// if num of weeks only
if (item.units.length === this.numOfWeeks) {
return false
}
// ...and the rest...
// Valid
return true;
})

How to filter values of an array inside an array?

I will describe the situation for more clarity. I have an array
like this
animalsArray = {
animalID : number,
animalName: string,
animalDescription: string,
animalChild: animalsArray[]
}
Now I have to filter these animals using animalName from user input by textfield. Some animals can have n number of animalChild or non at all or animalChild can have another animalChild inside it.
I already have a code like this
public animalsArray:animalsArray[]
this.filteredanimalsArray.next(
this.animalsArray.filter(item => (item.animalName.toLowerCase().indexOf(search) > -1))
);
To filter the main animalsArray and it works fine but the user input doesn't go through the child arrays.
How can I solve this problem? Thanks in advance
Maybe you could use recursivity like this :
function filterAnimals(animals, name) {
return animals.filter(animal => {
const matching = animal.animalName.toLowerCase() === name.toLowerCase();
const hasChildMatch = Array.isArray(animal.animalChild) && filterAnimals(animal.animalChild, name).length > 0;
return matching || hasChildMatch;
});
}
const search = 'leon';
const filterdAnimals = filterAnimals(animalsArray, search);

Sort array based on intermediate model's attribute

I have three models (I am using Vue/Vuex-ORM on the frontend). Category, CategoryItem and Item.
I'm able to fetch an array of categories, and within each category is an array of items. An intermediate join model defines the relationships of these two models, and I am able to access as such:
// array of categories, each category has array of items
const categories = Category.query().where('pack_id', this.selectedPack.id).with('items').get();
categories.map(category => {
category.items.forEach(item => {
console.log('item.pivot: ', item.pivot); // pivot refers to join model
// how to order items based on item.pivot?
})
})
Within the .forEach, I can access the join model with item.pivot. What I am looking to do however, is sort each category's items based on item.pivot.position.
I started going down a path where the first line inside of the .map I defined a new empty array, and would then theoretically push in a new value based on whether the position was higher or lower, but I couldn't quite wrap my head around how to accomplish this.
Thanks!
Well just my luck. A half hour after posting this question, I figure it out! Here was what I did, in case anyone is curious.
categories() {
const categories = Category.query().where('pack_id', this.selectedPack.id).with('items').get();
categories.forEach(category => category.items.sort(this.compare));
return cats;
}
compare(a, b) {
let comparison = 0;
if (a.pivot.position > b.pivot.position) comparison = 1;
else if (a.pivot.position < b.pivot.position) comparison = -1;
return comparison;
},

Use "include" for ANY string in a array

I have a search function that takes input/query text from a search bar. I want it to work for multiple search terms like "javascript react" or with more or less search terms. The input is saved in an array in state ("query") and compares to an object "workitem" and its property "description".
Let say:
workitem.description.includes(this.state.query)
where
this.state.query // = ["react", "javacript"]
Above will only work for certain situations. I want to see if the array/object includes ANY elements of the state. How to do it?
// if needed, do a
// if (!workitem.description || !this.state.query) {
// return false;
// }
Considering description is an array:
return workitem.description.some(desc => this.state.query.indexOf(desc) >= 0)
Considering description is a string:
return workitem.description
.split(' ')
.some(desc => state.query.indexOf(desc) >= 0);
How about this:
workitem.description.split(' ').some(str => this.state.query.includes(str))

How to use forEach to update all values matching this criteria

I am creating a function for selecting/deselecting checkboxes representing objects in my array.
Currently I have:
selectAll(allType: string, state) {
this.modalData.columnPermissions.forEach(a =>
a["can" + allType] = state
);
}
(allType allows me to target "canRead" or "canWrite" keys depending on which SELECT ALL the user chooses from the top of 2 columns.)
This is working fine - however a scenario has now been introduced where if an object contains the property IDM=TRUE then "canWrite" should always be FALSE
I'm struggling on how to now adapt my selectAll function to exclude any object with a property of IDM=TRUE on the KEY canWrite
Any help is appreciated
I have resolved this with info from depperm
this.modalData.columnPermissions.forEach(a => {
if (allType === 'Write' && !a.IDM) {
a["can" + allType] = state
} else if (allType === 'Read') {
a["can" + allType] = state
}
})

Categories

Resources