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;
})
Guys I want to get an element from array. Here:
Follower:
{ follower:
[ 5edfe8f3bfc9d677005d55ca,
5edfe92fbfc9d677005d55cc,
5ee2326cc7351c5bb0b75f1a ],
user id:
5edfe92fbfc9d677005d55cc
The process:
if(follower == user){
console.log("sdasdsad")
}else{
console.log("no")
}
But when I do it it always returns as no.
Also this is the codes of===> Nodejs Follow System Not Working Properly
It is a nodejs project. So please look at the above link.
When I do
if(follower.includes(user)){
It gives the error of:
TypeError: Cannot read property 'includes' of null
And when I try to change some I get this error:
TypeError: takip.includes is not a function
Guys so thats why I say please look at the above code.
So how to equalize them?
As other peoples said earlier the follower itself is a property which its value is an array itself, so if you want to check whether an item exists within it or not you can check it with includes(), if it exists it will return true otherwise it will return false.
const follow = {
follower: ["5edfe8f3bfc9d677005d55ca",
"5edfe92fbfc9d677005d55cc",
"5ee2326cc7351c5bb0b75f1a"
]
}
const user = "5edfe92fbfc9d677005d55cc";
if (follow.follower.includes(user)) {
console.log("sdasdsad")
} else {
console.log("no")
}
But if you looking to find the exact position of the item within that array you can find it with indexOf(). If the item does not exist within the array it will return -1, otherwise, it will return the index of that item within the array.
const follow = {
follower: ["5edfe8f3bfc9d677005d55ca",
"5edfe92fbfc9d677005d55cc",
"5ee2326cc7351c5bb0b75f1a"
]
}
const user = "5edfe92fbfc9d677005d55cc";
console.log(follow.follower.indexOf(user));
You are trying to compare a string to an array so it will never pass the if statement.
If you change your if to be if ( follower.includes(user)) { then it will search the array for the string.
var follower = [
'5edfe8f3bfc9d677005d55ca',
'5edfe92fbfc9d677005d55cc',
'5ee2326cc7351c5bb0b75f1a'
]
var user = '5edfe92fbfc9d677005d55cc'
// This will always fail as follower is an array not a string
if (follower.includes(user)){
console.log("sdasdsad")
} else {
console.log("no")
}
References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
Looks like follower is a property. You can use this solution:
objectName.follower.forEach(item =>
if (item == user) console.log(`${item} is the answer`);
);
This way, javascript will go through all of the elements in the array and print it out if it is matching with your user variable.
You can also use for loop or while loop for the same process, however, since you're using an array, forEach will be much more useful.
If this was not your question and I misunderstood your question, let me know, I'll see if I can help.
I hope this helps
var obj = {
follower: [ '5edfe8f3bfc9d677005d55ca',
'5edfe92fbfc9d677005d55cc',
'5ee2326cc7351c5bb0b75f1a'
]
};
var userId = '5edfe92fbfc9d677005d55cc';
function searchUser(object, user){
if(obj.follower.includes(user)){
return object.follower.filter(x => x == user);
} else {
return 'no';
}
};
console.log(searchUser(obj, userId));
You can use Array.protorype.some() to check if user exists in the follower array.
const obj = {
follower: [
"5edfe8f3bfc9d677005d55ca",
"5edfe92fbfc9d677005d55cc",
"5ee2326cc7351c5bb0b75f1a"
]
}
const user = "5edfe92fbfc9d677005d55cc";
if(obj.follower.some(item => item === user)) {
console.log("found")
} else{
console.log("no")
}
You can also get the item with Array.protorype.find() with the same way as above, just assign it to a variable
Array.prototype.some
Array.prototype.find
I have an array of some class names that all of the values in that array end with numbers. I want to have a function that when I give it a number, it search through that array, and check the last 3 digits of each value, to find the matching number and return that matching value.
So lets say, I give it value 200 and it searches through the array and returns wi-owm-200.
I manage to make it but it does not return it. It does find the value, but when it is outside of the function, it returns 'undefined'.
Here is my code: Fiddle
var owmIcon = ["wi-owm-200", "wi-owm-201", "wi-owm-202", "wi-owm-210", "wi-owm-211", "wi-owm-212", "wi-owm-221", "wi-owm-230", "wi-owm-231", "wi-owm-232", "wi-owm-300", "wi-owm-301", "wi-owm-302", "wi-owm-310", "wi-owm-311", "wi-owm-312", "wi-owm-313", "wi-owm-314", "wi-owm-321", "wi-owm-500", "wi-owm-501", "wi-owm-502", "wi-owm-503", "wi-owm-504", "wi-owm-511", "wi-owm-520", "wi-owm-521", "wi-owm-522", "wi-owm-531", "wi-owm-600", "wi-owm-601", "wi-owm-602", "wi-owm-611", "wi-owm-612", "wi-owm-615", "wi-owm-616", "wi-owm-620", "wi-owm-621", "wi-owm-622", "wi-owm-701", "wi-owm-711", "wi-owm-721", "wi-owm-731", "wi-owm-741", "wi-owm-761", "wi-owm-762", "wi-owm-771", "wi-owm-781", "wi-owm-800", "wi-owm-801", "wi-owm-802", "wi-owm-803", "wi-owm-804", "wi-owm-900", "wi-owm-901", "wi-owm-902", "wi-owm-903", "wi-owm-904", "wi-owm-905", "wi-owm-906", "wi-owm-957"];
var res = findOWMIcon("200");
console.log(res);
function findOWMIcon(num) {
$.each(owmIcon, function(key, value) {
var classNum = value.substr(value.length - 3);
if (parseInt(num, 10) === parseInt(classNum, 10)) {
console.log(value);
return value;
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Any idea how to solve it? So I can get the found value outside the function?
This is sufficient:
owmIcon.filter(e => e.slice(-3) == "200");
// Get all elements that ends in "01"
items = get_all_items().filter(e => e.slice(-2) == "01");
console.log(items);
function get_all_items(){
return ["wi-owm-200", "wi-owm-201", "wi-owm-202", "wi-owm-210", "wi-owm-211", "wi-owm-212", "wi-owm-221", "wi-owm-230", "wi-owm-231", "wi-owm-232", "wi-owm-300", "wi-owm-301", "wi-owm-302", "wi-owm-310", "wi-owm-311", "wi-owm-312", "wi-owm-313", "wi-owm-314", "wi-owm-321", "wi-owm-500", "wi-owm-501", "wi-owm-502", "wi-owm-503", "wi-owm-504", "wi-owm-511", "wi-owm-520", "wi-owm-521", "wi-owm-522", "wi-owm-531", "wi-owm-600", "wi-owm-601", "wi-owm-602", "wi-owm-611", "wi-owm-612", "wi-owm-615", "wi-owm-616", "wi-owm-620", "wi-owm-621", "wi-owm-622", "wi-owm-701", "wi-owm-711", "wi-owm-721", "wi-owm-731", "wi-owm-741", "wi-owm-761", "wi-owm-762", "wi-owm-771", "wi-owm-781", "wi-owm-800", "wi-owm-801", "wi-owm-802", "wi-owm-803", "wi-owm-804", "wi-owm-900", "wi-owm-901", "wi-owm-902", "wi-owm-903", "wi-owm-904", "wi-owm-905", "wi-owm-906", "wi-owm-957"];
}
Use function(e){ return e.slice(-3) == "200"; } instead of e => ... if you care about backward compatibility (ES5 and before).
let data = ["wi-owm-200", "wi-owm-201", "wi-owm-202", "wi-owm-210", "wi-owm-211", "wi-owm-212", "wi-owm-221", "wi-owm-230", "wi-owm-231", "wi-owm-232", "wi-owm-300", "wi-owm-301", "wi-owm-302", "wi-owm-310", "wi-owm-311", "wi-owm-312", "wi-owm-313", "wi-owm-314", "wi-owm-321", "wi-owm-500", "wi-owm-501", "wi-owm-502", "wi-owm-503", "wi-owm-504", "wi-owm-511", "wi-owm-520", "wi-owm-521", "wi-owm-522", "wi-owm-531", "wi-owm-600", "wi-owm-601", "wi-owm-602", "wi-owm-611", "wi-owm-612", "wi-owm-615", "wi-owm-616", "wi-owm-620", "wi-owm-621", "wi-owm-622", "wi-owm-701", "wi-owm-711", "wi-owm-721", "wi-owm-731", "wi-owm-741", "wi-owm-761", "wi-owm-762", "wi-owm-771", "wi-owm-781", "wi-owm-800", "wi-owm-801", "wi-owm-802", "wi-owm-803", "wi-owm-804", "wi-owm-900", "wi-owm-901", "wi-owm-902", "wi-owm-903", "wi-owm-904", "wi-owm-905", "wi-owm-906", "wi-owm-957"];
// Suppose you want to get all elements that end with 200, so...
let filteredData = data.filter(item => item.slice(-3) === "200");
console.log(filteredData);
I have the following object:
var oBadge = {
COMMENT_CREATED: {
FIRST_COMMENT_CREATED: {
code: "FIRST_COMMENT_CREATED",
src: "",
name: "Socializer",
text: "Create a comment for an idea",
condition: {
today: null,
over_all: 1
}
}
}
};
i need to check if a string i get (for example "FIRST_COMMENT_CREATED") is contained in the oBadge model. The object contains more elements - not only the comment_created element. Therefore i cannot define to check it there.
I found the following function to determine wether the element is contained within the object or not, but I also need the contained data, not only the statement whether it is contained or not.
oBadge.hasOwnProperty("FIRST_COMMENT_CREATED")
What i'm basically looking for is a way to skip the second hierachy level on my check - like:
if(oBadge.[<all>]["FIRST_COMMENT_CREATED"] !== undefined) {
// return data
}
There is no way to skip the hierarchy without looping through the object, you should use the for...in loop:
for (var prop in oBadge) {
if(oBadge[prop].hasOwnProperty("FIRST_COMMENT_CREATED")) {
// return data
}
}
Use a function and a loop (for-in):
function find(key, obj){
if(!obj.hasOwnProperty) return false; // no primitive data please!
if(obj.hasOwnProperty(key))
return obj[key];
else return false;
}
for(var key in oBadge){
if(find("FIRST_COMMENT_CREATED", key))
// code
}