creating a javascript recursive filter function - javascript

Is there any way of making this function recursive so that I do not need to create a switch for each length of filter criteria ?
var data = [
{a:'aaa',b:'bbb',c:'ccc',d:'ddd',e:'eee'},
{a:'aaa',b:'bbb',c:'ccc',d:'eee',e:'fff'},
{a:'xxx',b:'bbb',c:'ccc',d:'ddd',e:'fff'}
]
function select(data,where){
return data.filter(function(e){
var k = Object.keys(where);
switch(k.length){
case 1: return (e[k[0]] == where[k[0]]);
case 2: return (e[k[0]] == where[k[0]] && e[k[1]] == where[k[1]]);
case 3: return (e[k[0]] == where[k[0]] && e[k[1]] == where[k[1]] && e[k[2]] == where[k[2]]);
case 4: return (e[k[0]] == where[k[0]] && e[k[1]] == where[k[1]] && e[k[2]] == where[k[2]] && e[k[3]] == where[k[3]]);
case 5: return (e[k[0]] == where[k[0]] && e[k[1]] == where[k[1]] && e[k[2]] == where[k[2]] && e[k[3]] == where[k[3]] && e[k[4]] == where[k[4]]);
}
})
}
var where = {a:'aaa',b:'bbb'}
console.log(select(data,where));

It doesn't need to be recursive (I'm not sure you understand what that means), you just need to loop on the elements in where:
function select(data, where) {
return data.filter(function(e) {
var k = Object.keys(where);
return k.every(function(key) {
return e[key] == where[key];
});
})
}
var data = [
{a:'aaa',b:'bbb',c:'ccc',d:'ddd',e:'eee'},
{a:'aaa',b:'bbb',c:'ccc',d:'eee',e:'fff'},
{a:'xxx',b:'bbb',c:'ccc',d:'ddd',e:'fff'}
]
var where = {a:'aaa',b:'bbb'}
console.log(select(data,where));

Try this code:
function select(data, where) {
return data.filter(function (e) {
for (var key in where) {
if (where.hasOwnProperty(key)) {
if (e.hasOwnProperty(key)) {
if (e[key] != where[key]) {
return false;
}
}
else {
return false
}
}
}
return true;
})
}

Related

Leetcode Same Tree Iterative Solution

Question at hand: https://leetcode.com/problems/same-tree/
Can someone point out why my JavaScript solution can pass the test cases but fails during the actual submission?
var isSameTree = function(p, q) {
let queue = [];
queue.push(p);
queue.push(q);
while (!queue.length) {
let p = queue.shift();
let q = queue.shift();
if (p == null && q == null) {
continue;
} else if (p == null || q == null || p.val != q.val) {
return false;
} else {
queue.push(p.left);
queue.push(q.left);
queue.push(p.right);
queue.push(q.right);
}
}
return true;
};
#trincot mentioned it in the comments.
Just update the comparison inside the while loop to get into that loop.
var isSameTree = function(p, q) {
let queue = [];
queue.push(p);
queue.push(q);
while (queue.length != 0) {
let p = queue.shift();
let q = queue.shift();
if (p == null && q == null) {
continue;
} else if (p == null || q == null || p.val != q.val) {
return false;
} else {
queue.push(p.left);
queue.push(q.left);
queue.push(p.right);
queue.push(q.right);
}
}
console.log(queue);
return true;
};
This will pass all the test cases.

DRY - Typescript. How can I use DRY principles to avoid duplication of these 2 getters

I know that below two getters are duplicates and could be consolidated and written in a better way. Could any one please help me come up with a way to consolidate these:-
isEqual here is a lodash library to compare two objects.
state in here is an injected state which I am picking the objects from.
public get isUpperModified(): boolean {
if (!this.isUpperAvailable) {
return false;
}
if (
(this.orders.upperPreference.type === '1' &&
this.state.fetchedData.upperPreference.type === '1') ||
(this.orders.upperPreference.type === 'UPPER' &&
this.state.fetchedData.upperPreference.type === 'UPPER')
) {
return false;
}
if (!isEqual(this.orders.upperPreference, this.state.fetchedData.upperPreference)) {
return true;
}
return false;
}
public get isLowerModified(): boolean {
if (!this.isLowerAvailable) {
return false;
}
if (
(this.orders.lowerPreference.type === '1' &&
this.state.fetchedData.lowerPreference.type === '1') ||
(this.orders.lowerPreference.type === 'LOWER' &&
this.state.fetchedData.lowerPreference.type === 'LOWER')
) {
return false;
}
if (!isEqual(this.orders.lowerPreference, this.state.fetchedData.lowerPreference)) {
return true;
}
return false;
}
There are more than 1 way to achieve this.
You can create a new function isModified(type: string) and pass upper or lower as an argument.
Hope this helps
public get isUpperModified(): boolean {
return this.isModified('upper');
}
public get isLowerModified(): boolean {
return this.isModified('lower');
}
private isModified(type: 'lower' | 'upper'): boolean {
const available = type === 'lower' ? this.isLowerAvailable : this.isUpperAvailable;
const order = type === 'lower' ? this.orders.lowerPreference : this.orders.upperPreference;
const state = type === 'lower' ? this.state.fetchedData.lowerPreference : this.state.fetchedData.upperPreference;
if (!available) {
return false;
}
if (
(order.type === '1' &&
state.type === '1') ||
(order.type === type.toUpperCase() &&
state.type === type.toUpperCase())
) {
return false;
}
if (!isEqual(order, state)) {
return true;
}
return false;
}
I would do it something like this
public get isModified(type: 'lower' | 'upper'): boolean {
const isAvailable = type === "lower" ? this.isLowerAvailable : this.isUpperAvailable
const preference = type === "lower" ? "lowerPreference" : "upperPreference";
if (!isAvailable) {
return false;
}
if (
(this.orders[preference].type === '1' &&
this.state.fetchedData[preference].type === '1') ||
(this.orders[preference].type === 'LOWER' &&
this.state.fetchedData[preference].type === 'LOWER')
) {
return false;
}
if (!isEqual(this.orders[preference], this.state.fetchedData[preference])) {
return true;
}
return false;
}
Then while calling this method
use isModified("upper") instead of isUpperModified
and
use isModified("lower") instead of isLowerModified

How to make multiple conditions inside single filter

I am trying to make a filter based on checkboxes.
The thing is js ignoring other conditions inside filter when one is active
filterData() {
return this.airlines.filter(x => {
if (this.filters.options.length != 0 || this.filters.airlines.length != 0) {
for (let i = 0; this.filters.options.length > i; i++) {
if (this.filters.options[i] == 0) {
return x.itineraries[0][0].stops == 0;
}
if (this.filters.options[i] == 1) {
return x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
}
}
} else {
return x;
}
})
}
I know that return will stop the current loop, but is there any way to do it correctly?
Update-1: (When to filter record for every case checked OR case)
Replace for loop and all conditions in a single return by && for if and || condition for data:
var chbox = this.filters.options;
return $.inArray(0, chbox) != -1 && x.itineraries[0][0].stops == 0
|| $.inArray(1, chbox) != -1 && x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
Hope this helps !!
$.inArray(value, arr) method will check for each checkboxes and will work for every checked ones .
Update-2 (When to filter record for every case checked AND case)
As per comment below, you are trying to use checkbox on demand so use below code:
var chbox = this.filters.options;
boolean condition = true;
if ($.inArray(0, chbox) != -1) {
conditon = conditon && x.itineraries[0][0].stops == 0;
}
if ($.inArray(1, chbox) != -1) {
conditon = conditon && x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
}
return condition;
Your filter function is returning an object, which ideally should be a boolean value. Please refactor the code as below.
filterData() {
return this.airlines.filter(x => {
let result = false;
if (this.filters.options.length != 0 || this.filters.airlines.length != 0) {
for (let i = 0; this.filters.options.length > i; i++) {
if (this.filters.options[i] == 0) {
result = x.itineraries[0][0].stops == 0;
break;
} else if (this.filters.options[i] == 1) {
result = x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
break;
}
}
}
return result;
})
}

How to optimize multiple filter?

I have big search panel with filters
In the computed section I use the next code
computed: {
filteredItems() {
if (this.activeFilter && this.activeFilter != 'all') {
return this.items[this.activeFilter]
.filter(item => item.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1)
.filter(item => item.itemLevel >= this.minLvl && item.itemLevel <= this.maxLvl);
} else {
let all = [];
let i;
if (this.items) {
for (i = 0; i < this.filters.length; i++) {
Array.prototype.push.apply(all, this.items[this.filters[i].value]);
}
}
return all
.filter(item => item.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1)
.filter(item => {
if (this.minLvl !== '' && this.maxLvl !== '') {
if (item.itemLevel >= this.minLvl && item.itemLevel <= this.maxLvl) return true;
} else if (this.minLvl == '' && this.maxLvl !== '') {
if (item.itemLevel <= this.maxLvl) return true;
} else if (this.minLvl !== '' && this.maxLvl == '') {
if (item.itemLevel >= this.minLvl) return true;
} else {
return true;
}
});
}
},
}
Here is I use one filter for min and max level. And when I will add more filter my code will be too big. Multiple filters can be active l at the same time.
How can I optimize my code?

Recursion Function to search

How would I go about creating a recursive function that can search through a list for a node where x = 10?
I do not have any javascript experience so I am not sure where to start so would appreciate and input
I have come across the following code and tried to adapt it but I am not sure if I am on the right track:
function search(_for, _in) {
var r;
for (var p in _in) {
if ( p === 10 ) {
return _in[p];
}
if ( typeof _in[p] === 'object' ) {
if ( (r = search(_for, _in[p])) !== null ) {
return r;
}
}
}
return null;
}
Thank you in advance
Try this
var finder = function(needle, haystack) {
if (haystack.length == 0)
return false
if (haystack[0] == needle)
return true
return finder(pin, haystack.slice(1))
}
Or
var finder = function(pin, haystack) {
return (haystack[0] == pin) || (haystack.length != 0) && finder(pin, haystack.slice(1))
}
Recursion FTW

Categories

Resources