I'm trying to solve this problem.
I'm creating a filter method, that has to return me a filtered array based on my preference.
The array is containing some sports bet info, like the odd quote, the starting date, the name of the bookmaker, etc, and I'm trying (for the moment) to just filter based on the min and max odds
First of all, into my "Parent" react component, I receive some info from his child, and those info are stored in an object.
The object is like that:
filters = {minOdd: "", maxOdds:"", ecc...}
And the filter method is like:
setFilters = () => {
const odds = this.state.odds
const filters = this.state.filters
const newOdds = odds.filter((odd) => odd.quota > filters.quotaMin)
.filter((odd) => odd.quota < filters.quotaMax)
}
Where "quota" means "odd", quotaMin means "min odd" and "quotaMax" means max odd
Now, if I set the min and the max odd into my child component, the function returns me an array containing all the right odds. But if I set just one of the 2 filters, this function returns me back an empty object.
I'n my opinion, the problem is that if i don't set one of the 2 value, the filter method compares the odd this a value that is like modd.quota < filters.quotaMax, where filters.quotaMax could be = to "".
Soo i have to not allow the filter method to filter value that are = to "".
If someone can give my an advice!
Thanks in advice!
Use fallback values for the undefined filters.
If either quotaMax or quotaMin is not defined, you are (most likely, haven't seen the structure of a bet) comparing a Number against undefined, which always results in false:
1 < undefined; // -> false
1 > undefined; // -> false
As fallback values, you can use negative and positive infinity. To be honest, it doesn't matter which values you use as long as the fallback for quotaMin is guaranteed to be smaller than the lowest quota and the fallback for quotaMax is guaranteed to be higher than the highest quota.
const newOdds = odds
.filter(odd => odd.quota > (filters.quotaMin || -Infinity))
.filter(odd => odd.quota < (filters.quotaMax || Infinity));
Side note:
You can make your code run faster by merging both predicates into one with AND && (saves one iteraton/filtering).
const newOdds = odds
.filter(odd => odd.quota > (filters.quotaMin || -Infinity) &&
odd.quota < (filters.quotaMax || Infinity));
I guess you just need to handle that case then where quotaMax is undefined/"":
const newOdds = odds.filter((odd) => odd.quota > filters.quotaMin)
.filter((odd) => {
if (filters.quotaMax) {
return odd.quota < filters.quotaMax
} else {
// you decide what should happen in this case..
// return true/false
})
Related
I want to show you which number of users I entered in the argument is the order of joining the server. Like = when i use .join 1 I want to show the 1st member join in to the server. I use
let arr = message.guild.members.filter(a => !a.user.bot).array().sort((b, a) => b.joinedTimestamp - a.joinedTimestamp)
let map = arr.indexOf(sesmi) + 1
this command for showing joing position but im so confused how can i do as i said?
Try this:
// if the first argument is not a number (this message is kind of bad so you can change it)
if (isNaN(args[0])) return message.reply('you must specify what number user you want to get!')
const members = message.guild.members.cache
.filter(member => !member.user.bot)
// sorted is a member on Discord's utility class Collection that doesn't modify the original collection
.sorted((a, b) => a.joinedTimestamp - b.joinedTimestamp)
.array()
// the number user to get
const n = Number(args[0])
// if there are not enough members
if (n > members.length) {
// You only really need this if there is ever going to be only 1 member in the server
// and if you care about grammar. You could also just do
// return message.reply(`there are only ${members.length} members!`)
const plural = members.length !== 1
return message.reply(`there ${plural ? 'are' : 'is'} only ${members.length} member${plural ? 's' : ''}!`)
}
message.channel.send(members[n - 1].user.tag)
I'm assuming args will be an array of strings with the arguments passed into the command (e.g. .join 1 will have the args ['1'].
I have a method that gets a list of saved photos and determines the number of photos listed. What I wish to do is return the number of photos that contain the text "Biological Hazards" in the name. Here is my code so far
getPhotoNumber(): void {
this.storage.get(this.formID+"_photos").then((val) => {
this.photoResults = JSON.parse(val);
console.log("photoResults", this.photoResults);
// photoResults returns 3 photos
// Hazardscamera_11576868238023.jpg,
// Biological Hazardscamera_11576868238023.jpg,
// Biological Hazardscamera_11576868351915.jpg
this.photoList = this.photoResults.length;
console.log("photoList", this.photoList); // returns 3
this.photoListTwo = this.photoResults.includes('Biological Hazards').length; // I wish to return 2
}).catch(err => {
this.photoList = 0;
});
}
Any help would be greatly appreciated.
Xcode log
[
One way to do this is to .filter() the array, and then calculate the length of that array.
this.photoListTwo = this.photoResults.filter(photoString => {
return photoString === 'Biological Hazards' //or whatever comparison makes sense for your data
}).length;
Quick solution for this (sorry for the lack of better formating, posting from mobile):
const array = ["Hazardscamera_11576868238023.jpg", "Biological Hazardscamera_11576868238023.jpg", "Biological Hazardscamera_11576868351915.jpg"];
const filterBioHazards = (str) => /Biological Hazards/.test(str);
console.log(array.filter(filterBioHazards).length);
// Prints 2
The method includes returns boolean to indicate whether the array contains a value or not. What you need is to filter your array and return its length after.
You need to replace the line:
this.photoListTwo = this.photoResults.includes('Biological Hazards').length;
By this:
this.photoListTwo = this.photoResults.filter(function(result) {return result.contains("Biological Hazards");}).length;
I have a case like where end user will enter a string in input field like
"(min > 0) and (max <= 100) and (average > 10)". I want convert this string into a possible conditions to filter the API response.
For example, my API response will be
{
"result":{
"name1":{
"min":20,
"max":30,
"average":15
},
"name2":{
"min":20,
"max":30,
"average":15
},
"name3":{
"min":40,
"max":40,
"average":20
},
"name4":{
"name":"name4",
"min":50,
"max":50,
"average":25
}
}
}
I need the user inputs to converted to a way (like objects) so that I can apply that on the response. I tried using regexp to find the matches but I am not able to do. Please suggest.
You can try following.
Create a function that takes 2 inputs the response object and the filter String
In the function, update the string so that all the and's are replaced with && and the variables in string is are accessed like keys from an object. Please note, this name should be same as the one that will be used in the function to evaluate the expression
Use Object.entries to create an array of all the entries in object and then on the array use Array.reduce, to reduce the array into an object along with filtering the items in array that match the criteria. To evaluate the expression use eval
let resp = {"result":{"name1":{"min":20,"max":30,"average":15},"name2":{"min":20,"max":30,"average":15},"name3":{"min":40,"max":40,"average":20},"name4":{"name":"name4","min":50,"max":50,"average":25}}};
let filterStr = "(min > 0) and (max <= 100) and (average > 10)";
function filterResult(obj, str) {
str = str.replace(/\(/g, "(v.").replace(/and/g, "&&");
return Object.entries(obj.result).reduce((a,[k,v]) => {
if(eval(str)) a.result[k]=v;
return a;
},{result:{}});
}
console.log(filterResult(resp, filterStr));
You can use reduce and eval to achieve what you are trying, without using any regex.
P.S.: eval is not recommended by most of the developers
const yourConditionString = "average > 20"
const filterArray = Object.keys(jsonData.result).reduce((arr, name) => {
let min = jsonData.result[name].min
let max = jsonData.result[name].max
let average = jsonData.result[name].average
return arr.concat(eval(yourConditionString) ? jsonData.result[name] : [])
}, [])
So, I'm writing a client-side search and I need to look through strings of Japanese characters. I'm wondering how to do this properly?... i.e. Do I change the format of the text into utf-8 something and then search the utf-8?
Example:
All my data has japaneseData.title : "フェリーチェ三田"
When I type in my search.value as : "フェ" using japaneseData.title.includes(search.value) I don't get a match...
How do I do this correctly?
Okay, after further inspection, the comments were correct and includes was finding the substring. This is all happening inside of a filter() and I'm trying to return the objects that match...
After changing my code to:
let filteredArrayofObjects = Lists.houseLists.filter(house => house.building_name.includes(query.search));
I was getting back some but not all. Problem cases:
"アーバイルスパシエ芝浦BAY-SIDE".includes("エ芝浦"); // this evaluates to true, but does not get included in my filtered array...
Okay, further digging, it seems the issue is I need to wait for the filter process before returning the results... haven't yet found a solution to that just yet.
async filter(arr, callback) {
return (await Promise.all(
arr.map(async item => {
return (await callback(item)) ? item : undefined;
})
)).filter(i => i !== undefined);
}
handleFilterLists = async (query = {}) => {
const { Lists } = this.props;
let searchResults = await this.filter(Lists.houseLists, async house => {
return house.building_name.includes(query.search);
// the final evaluation to look similar to this:
// var newArray = homes.filter(function (el) {
// return el.price <= 1000 &&
// el.sqft >= 500 &&
// el.num_of_beds >=2 &&
// el.num_of_baths >= 2.5;
// });
});
this.setState({ searchResults });
}
Okay, so, I'm trying to set state.searchResults after the filter method has checked for matching objects in the array Lists.houseLists...
includes returns true or false if the substring is detected or not. If you want the index of where the first detected substring begins, use indexOf.
I used your sample source and search text with includes and it returns true.
Edit:
I used your updated data and this still works. https://codepen.io/anon/pen/RMWpwe
const sourceText = 'アーバイルスパシエ芝浦BAY-SIDE';
const searchText = 'エ芝浦';
const lists = [
'スパシエ',
'芝浦BAY-SIDE',
'エ芝浦',
'パシエ芝浦BAY'
];
console.log(lists.filter(item => item.includes(searchText)));
// ["エ芝浦", "パシエ芝浦BAY"]
I'm trying to find similar items amongs a dynamic amount of arrays, For example I might have 2 or 3 arrays with data in them, and want to find the which items exist between all of them.
At the minute i've got this "working" but really ugly code which won't scale past 3 items. The GDAX, PLNX etc are all bools which I have available to tell me whether this option is selected.
The intersectionBy is a lodash helper function with further information available here https://lodash.com/docs/4.17.4#intersectionBy
let similarItems = [];
similarItems = GDAX && PLNX && BTRX ? _.intersectionBy(data.BTRX, data.PLNX, data.GDAX, 'pair') : similarItems;
similarItems = GDAX && PLNX && !BTRX ? _.intersectionBy(data.PLNX, data.GDAX, 'pair') : similarItems;
similarItems = GDAX && !PLNX && BTRX ? _.intersectionBy(data.BTRX, data.GDAX, 'pair') : similarItems;
similarItems = !GDAX && PLNX && BTRX ? _.intersectionBy(data.BTRX, data.PLNX, 'pair') : similarItems;
This should do the job
const input = ['GDAX', 'PLNX', 'BTRX']; // here you pass the strings that are given
const result = _.intersectionBy.apply(_, input.map(name => data[name]).concat(['pair']));
The input could also somehow automized, e.g. giving the object of true / false values for each name, so
const inputObject = { GDAX: true, PLNX: false, BTRX: true };
const names = ['GDAX', 'PLNX', 'BTRX'].filter(name => inputObject[name]);
const result = _.intersectionBy.apply(_, names.map(name => data[name]).concat(['pair']));
For readability and easy maintainability, I'd go with explicitly building a selection according to your boolean flags:
let selection = [];
if (GDAX) selection.push(data.GDAX);
if (PLNX) selection.push(data.PLNX);
if (BTRX) selection.push(data.BTRX);
const result = _.intersectionBy(...selection, 'pair');