Filtering multiple input fields - javascript

I'm trying to create a filter with javascript with 4 input fields so I'm guessin 16 combinations of possible searches. I can search all 4 at once or 1 input at a time but for some reason when I add other statements I get wierd results. Is there a better way to implement a filter?
var unfilteredFloorplans = floorplanJSON.floorplanData;
filteredFloorplans = [];
for (var i = 0; i < unfilteredFloorplans.length; i++) {
if (unfilteredFloorplans[i].city == req.body.cityName &&
unfilteredFloorplans[i].building == req.body.buildingName &&
unfilteredFloorplans[i].bedrooms == req.body.minBedroom &&
unfilteredFloorplans[i].baths == req.body.maxBathroom) {
console.log(unfilteredFloorplans[i].city);
filteredFloorplans.push(unfilteredFloorplans[i]);
}
}
So now I need to write 15 more if statements? Rather than copy them in I'd like to ask if this is correct and does anyone know how you could implement this with a switch statement?
Edit: And when I say 15 more statements I mean one for if they just pick city, andother if they pick city and bedrooms etc. It just seems inefficient

A minimal fix would be to combine your "and" with "or", but note how this turns the code into a hard-to-read mess:
var unfilteredFloorplans = floorplanJSON.floorplanData;
filteredFloorplans = [];
for (var i = 0; i < unfilteredFloorplans.length; i++) {
if ((req.body.cityName == '' || unfilteredFloorplans[i].city == req.body.cityName) &&
(req.body.buildingName == '' || unfilteredFloorplans[i].building == req.body.buildingName) &&
(req.body.minBedroom == '' || unfilteredFloorplans[i].bedrooms == req.body.minBedroom) &&
(req.body.maxBathroom == '' || unfilteredFloorplans[i].baths == req.body.maxBathroom)) {
console.log(unfilteredFloorplans[i].city);
filteredFloorplans.push(unfilteredFloorplans[i]);
}
}
(BTW, this looks like a good exercise for combining conjunctions with disjunctions.)
Edit I'd recommend to put the filtering into a separate function, and to introduce an additional helper function. Also, use a more consistent naming and use "===" instead of "==".
function filterByEquality(formValue, dataValue) {
if (formValue === '') return true;
if (formValue === dataValue) return true;
return false;
}
function filterFloorplan(form, data) {
if (!filterByEquality(form.city, data.city)) return false;
if (!filterByEquality(form.building, data.building)) return false;
if (!filterByEquality(form.minBedrooms, data.bedrooms)) return false;
if (!filterByEquality(form.maxBathrooms, data.bathrooms)) return false;
return true;
}
var unfilteredFloorplans = floorplanJSON.floorplanData;
filteredFloorplans = [];
for (var i = 0; i < unfilteredFloorplans.length; i++) {
if (filterFloorplan(req.body, unfilteredFloorplans[i]);
console.log(unfilteredFloorplans[i].city);
filteredFloorplans.push(unfilteredFloorplans[i]);
}
}
You can reduce this code even further by learning about the Array.filter method. And you should fix the bug where for some fields should use ">=" or ">=" instead of "===". But I'll leave those things as an exercise.

Here's a simplified example of what your code may look like (in this example, I hardcoded the values representing the input choices):
var unfilteredFloorplans = [{
city: 'NY',
building: 'A',
bedrooms: 2,
baths: 1,
}];
var filteredFloorplans = unfilteredFloorplans.filter(
function(el) {
return el.city === 'NY' && el.building === 'A' && el.bedrooms >= 1 && el.baths >= 1;
}
);
console.log(filteredFloorplans);
The anonymous function being called inside the filter can be replaced with a named function like so:
function filterFloorplans(floorplan) {
return floorplan.city === 'NY' && floorplan.building === 'A' && floorplan.bedrooms >= 1 && floorplan.baths >= 1;
}
var filteredFloorplans = unfilteredFloorplans.filter(filterFloorplans);
You'll likely want to use this route since you can have any combination of the 4 input choices. As such, you'll want the filterFloorplans function to be "built-up" from other, smaller checks:
function testCity(userInputCity, floorplanCity) {
return userInputCity ? userInputCity === floorplanCity : true;
}
function filterFloorplans(floorplan) {
return testCity('NY', floorplan.city) && floorplan.building === 'A' && floorplan.bedrooms >= 1 && floorplan.baths >= 1;
}
This should be enough to get you started; feel free to comment if you get stuck

Related

I failed Javascript tech interview but I dont know why

I was only allowed to use google document for writing.
Could you please tell me what I did wrong? The recruiter wont get back to me when I asked her why I failed
Task 1:
Implement function verify(text) which verifies whether parentheses within text are
correctly nested. You need to consider three kinds: (), [], <> and only these kinds.
My Answer:
const verify = (text) => {
   const parenthesesStack = []; 
   
  for( let i = 0; i<text.length; i++ ) {
const closingParentheses = parenthesesStack[parenthesesStack.length - 1]
if(text[i] === “(”  || text[i] === “[” || text[i] === “<”  ) {
parenthesisStack.push(text[i]);
} else if ((closingParentheses === “(” && text[i] === “)”) || (closingParentheses === “[” && text[i] === “]”) || (closingParentheses === “<” && text[i] === “>”) ) {
   parenthesisStack.pop();
} 
  };
return parenthesesStack.length ? 0 : 1;  
}
Task 2:
Simplify the implementation below as much as you can.
Even better if you can also improve performance as part of the simplification!
FYI: This code is over 35 lines and over 300 tokens, but it can be written in
5 lines and in less than 60 tokens.
Function on the next page.
// ‘a’ and ‘b’ are single character strings
function func2(s, a, b) {
var match_empty=/^$/ ;
if (s.match(match_empty)) {
return -1;
}
var i=s.length-1;
var aIndex=-1;
var bIndex=-1;
while ((aIndex==-1) && (bIndex==-1) && (i>=0)) {
if (s.substring(i, i+1) == a)
aIndex=i;
if (s.substring(i, i+1) == b)
bIndex=i;
i--;
}
if (aIndex != -1) {
if (bIndex == -1)
return aIndex;
return Math.max(aIndex, bIndex);
} else {
if (bIndex != -1)
return bIndex;
return -1;
}
};
My Answer:
const funcSimplified = (s,a,b) => {
if(s.match(/^$/)) {
return -1;
} else {
return Math.max(s.indexOf(a),s.indexOf(b))
}
}
For starters, I'd be clear about exactly what the recruiter asked. Bold and bullet point it and be explicit.
Secondly, I would have failed you from your first 'for' statement.
See my notes:
// Bonus - add jsdoc description, example, expected variables for added intention.
const verify = (text) => {
// verify what? be specific.
const parenthesesStack = [];
for( let i = 0; i<text.length; i++ ) {
// this could have been a map method or reduce method depending on what you were getting out of it. Rarely is a for loop like this used now unless you need to break out of it for performance reasons.
const closingParentheses = parenthesesStack[parenthesesStack.length - 1]
// parenthesesStack.length - 1 === -1.
// parenthesesStack[-1] = undefined
if(text[i] === “(” || text[i] === “[” || text[i] === “<” ) {
parenthesisStack.push(text[i]);
// “ will break. Use "
// would have been more performant and maintainable to create a variable like this:
// const textOutput = text[i]
// if (textOutput === "(" || textOutput === "[" || textOutput === "<") {
parenthesisStack.push(textOutput)
} else if ((closingParentheses === “(” && text[i] === “)”) || (closingParentheses === “[” && text[i] === “]”) || (closingParentheses === “<” && text[i] === “>”) ) {
parenthesisStack.pop();
// There is nothing in parenthesisStack to pop
}
};
return parenthesesStack.length ? 0 : 1;
// Will always be 0.
}
Not exactly what the intention of your function or logic is doing, but It would fail based on what I can see.
Test it in a browser or use typescript playground. You can write javascript in there too.
Hard to tell without the recruiter feedback. But i can tell that you missundertood the second function.
func2("mystrs", 's', 'm') // returns 5
funcSimplified("mystrs", 's', 'm') // returns 3
You are returning Math.max(s.indexOf(a),s.indexOf(b)) instead of Math.max(s.lastIndexOf(a), s.lastIndexOf(b))
The original code start at i=len(str) - 1 and decrease up to 0. They are reading the string backward.
A possible implementation could have been
const lastOccurenceOf = (s,a,b) => {
// Check for falsyness (undefined, null, or empty string)
if (!s) return -1;
// ensure -1 value if search term is empty
const lastIndexOfA = a ? s.lastIndexOf(a) : -1
const lastIndexOfB = b ? s.lastIndexOf(b) : -1
return Math.max(lastIndexOfA, lastIndexOfB)
}
or a more concise example, which is arguably worse (because less readable)
const lastOccurenceOf = (s,a,b) => {
const safeStr = s || '';
return Math.max(safeStr.lastIndexOf(a || undefined), safeStr.lastIndexOf(b || undefined))
}
I'm using a || undefined to force a to be undefined if it is an empty string, because:
"canal".lastIndexOf("") = 5
"canal".lastIndexOf(undefined) = -1
original function would have returned -1 if case of an empty a or b
Also, have you ask if you were allowed to use ES6+ syntax ? You've been given a vanilla JS and you implemented the equivalent using ES6+. Some recruiters have vicious POV.

Why does function return undefined?

So, I've recently started leaning how to code and I am trying to figure out how to create a function that will take a string and add the suffix 'ay' to the end if the conditions are met. For some reason, I keep getting 'undefined' whenever I run the function. I've tried rewriting it a few times but I keep getting something wrong and I can't figure out what it is! If someone can look this over and explain what I'm missing I would really appreciate it!
function translate(val) {
let piggy = 'ay'
let newVal = Array.from(val);
let finalVal;
let i = 0;
while (i < newVal - 1) {
if (newVal[0] == 'a' || newVal[0] == 'e' || newVal[0] == 'i' || newVal[0] == 'o' || newVal[0] == 'u') {
finalVal = newVal.join('') + piggy;
return finalVal;
} else {
finalVal = newVal;
return finalVal;
}
i++
}
}
translate('apple')
At a glance, you're subtracting a number from an array. This returns NaN and doesn't even hit the while loop. (x < NaN is always false)
Because you're not hitting the while loop the function just exists and never returns a value. That is why you receive undefined.
If you want to iterate over your newly created array, you'll want to use newVal.length.
Fixed code is as follows:
let piggy = 'ay'
let newVal = Array.from(val);
let finalVal;
let i = 0;
while (i < newVal.length - 1) {
if (newVal[0] == 'a' || newVal[0] == 'e' || newVal[0] == 'i' || newVal[0] == 'o' || newVal[0] == 'u') {
finalVal = newVal.join('') + piggy;
return finalVal;
} else {
finalVal = newVal;
return finalVal;
}
i++
}
}
translate('apple')
You're missing a return statement, and I'm not sure what you are trying to do here... Are you trying to append 'ay' to the string, if it starts with a vowel?
if yes, this is a simplified version of your code :
function translate( val ) {
if([ "a", "e", "i","o","u"].includes(val[0])) {
return val + 'ay';
}
else return val;
}

Unsure of how to make this calculator function work

Link to Codepen
For a math project due very soon.
I've tried to apply the DRY concept, but I don't know how. I started to write a function that would apply for all of the numbers, but halfway through it I realized there's no way it would work. The anonymous functions need to be changed I know that, yet I can't right now as I don't know another way to implement it.
document.querySelector(".button").addEventListener("click", function) {
num = document.getElementById('something');
if (num != null && num === document.getElementById("zero")) {
calculation = calculation.concat("0");
} else if (num != null && num === document.getElementById("one")) {
calculation = calculation.concat("1");
} else if (num != null === && num document.getElementbyId("two")) {
calculation = calculation.concat("2");
} else if (num != nul && num === document.getElementbyId("three")) {
calculation = calculation.concat("3");
} else if (num != nul && num === document.getElementbyId("four")) {
calculation = calculation.concat("4");
} else if (num != nul && num === document.getElementbyId("five")) {
calculation = calculation.concat("5");
} else if (num != nul && num === document.getElementbyId()) {
calculation = calculation.concat("6");
}
}
Each number is inside a button which is inside a table. They also have id's identifying which number they are. I'm not looking for code, don't want to plagiarize anything. Just looking for suggestions on what I could do differently.
Your easiest method will be writing a common function:
var buttons = document.querySelectorAll("button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener(
"click",
function() {
var current_value = this.innerHTML; //typed single number
var display_value = document.getElementById('display').value; //the value on the calculator display
var new_value = display_value + '' + current_value; //+''+ to make it string
document.getElementById('display').value = new_value;
});
}
Try this and add exceptions and calculation functions with same method as above by filtering '+','-', etc. values.
i think its easier if you use jquery..just a suggestion.
please see the fiddle.
i have added a class 'show' to all buttons which we want to display on the screen on click and class 'calc' for all operator buttons..replaced your display javascript with the following jquery
var calculation='';
$('button.show').click(function(){
calculation = calculation.concat($(this).text());
$('#screen').text(calculation);
});
And also added scripts for the calculation
Please see the fiddle Updated Fiddle

angular2 filter-pipe with many categories and combinations

I'm trying to implement an angular 2 filter where the user should able to filter by a set of categories. Where the filtered result should include any object that has at least one field matching one of the categories that the user has chosen to filter by.
As for now I have 2 categories and have been able to do all of this "manually" but now I need to do this with up to 20 categories and I'm looking for a generic way to do this.
Consider this for an example (what I use now to filter by gender):
transform(value) {
if(value == null) {
return null;
}
// NO FILTER AT ALL //////
//If no filter is selected
if(this.SearchService.filterFemale == 0 && this.SearchService.filterMale == 0){
return value.filter(company => {
return company;
});
}
//If Female only
if(this.SearchService.filterFemale !== 0 && this.SearchService.filterMale == 0){
return value.filter(company => {
var i;
for (i = 0; i < company.audience.targetGroup.genders.length; i++) {
if(company.audience.targetGroup.genders[i].gender === 'Female'){
return company.audience.targetGroup.genders[i].gender === 'Female';
}
}
});
}
//If Male only
if(this.SearchService.filterFemale == 0 && this.SearchService.filterMale !== 0){
return value.filter(company => {
var i;
for (i = 0; i < company.audience.targetGroup.genders.length; i++) {
if(company.audience.targetGroup.genders[i].gender === 'Male'){
return company.audience.targetGroup.genders[i].gender === 'Male';
}
}
});
}
//If both Male and Female
if(this.SearchService.filterFemale !== 0 && this.SearchService.filterMale !== 0){
return value.filter(company => {
var i;
for (i = 0; i < company.audience.targetGroup.genders.length; i++) {
if(company.audience.targetGroup.genders[i].gender === 'Female' || company.audience.targetGroup.genders[i].gender === 'Male'){
return company.audience.targetGroup.genders[i].gender === 'Female' || company.audience.targetGroup.genders[i].gender === 'Male';
}
}
});
}
}
This works fine, however, lets say I have 15-20 categories to filter by and need the same logic this would be a real pain to write the code for with all the possible combinations there are.
For example: If in my case, a company object hold 4 chosen categories and a user then filters by 3 categories out of 15 possible where 2/3 of them match with the 4 categories the company has chosen then that company should be returned. Essentially, I'm looking for the same logic in the example above but it should work with any number of categories.
I've followed this example in my code. Where it is suggested that this is a similar mechanism as to how array.prototype.filter works, though, I can't figure out how I would use it in my example.
Any help is appreciated.

Angular function to take row from model

I have an angularjs function whereby the hope is to take a row away from $scope.model.insuredContact using the splice function. Unfortunately right now it seems the line of code below simply returns the row that hypothetically would be taken away...if that makes any sense? Meaning it just returns the row we are try eliminate but it doesn't really take it out of the array. How to do? Any help would be most appreciated.
$scope.txtChanged = function (i) {
var x = $scope.model.insuredContact[i];
if ((x.ContactName === '' || x.ContactName == undefined) && (x.ContactEmail === '' || x.ContactEmail == undefined) && (x.ContactPhone === '' || x.ContactPhone == undefined)) {
if (i == $scope.model.insuredContact.length - 1) { return; }
$scope.model.insuredContact = $scope.model.insuredContact.splice(i, 1);
}
}

Categories