Reputation: 51
I have multiple if statements which I have presented using ternary operator and then for each If a separate filter, This works perfectly fine in React, but the repetition of filter statement makes the code look untidy, id there a way to remove this repetition?
let ar = data;
id === 'A' ? ar = ar.filter(item => item > 4) : Id === 'B' ? ar = ar.filter(item => item > 4
&& item < 8) : Id === 'C' ? ar = ar.filter(item => item >8 && item < 15) : ar = data;
Upvotes: 1
Views: 91
Reputation: 3230
Let's run through some refactoring and see what we can improve. First I'll split it across multiple lines just so that I can see it easier:
let ar = data;
id === 'A' ?
ar = ar.filter(item => item > 4) :
id === 'B' ?
ar = ar.filter(item => item > 4 && item < 8) :
id === 'C' ?
ar = ar.filter(item => item > 8 && item < 15) :
//default
ar = data;
First thing I notice is that you are assigning multiple times, but using a ternary, which makes that unneeded. Let's fix that:
let ar = data
ar = (
id === 'A' ?
ar.filter(item => item > 4) :
id === 'B' ?
ar.filter(item => item > 4 && item < 8) :
id === 'C' ?
ar.filter(item => item > 8 && item < 15) :
//default
data
)
Next, ar.filter
is getting called every time (except for the default case), and only the arguments are changing. The default case can be changed to be a filter that returns everything so that it is more consistent, and then we can extract the arguments to a variable (let's call it filter
):
let ar = data
// we are just determining the argument here
let filter = (
id === 'A' ?
item => item > 4 :
id === 'B' ?
item => item > 4 && item < 8 :
id === 'C' ?
item => item > 8 && item < 15 :
// default is to return all items
item => true
)
// now we can use the argument in the function call
ar = ar.filter(filter)
That removes most of the duplication here, but we are comparing to id
in the same way multiple times. Like Pavlos
mentioned, if you want to pick an option based on a string id, basic objects can let you do that. The problem is we loose our default argument, but we can usually use the ||
("or") operator to fix that:
let ar = data
// another benefit of doing it this way is that it is super easy to add
// new filters now, and you can even pass this in as a prop to your component.
let filters = {
'A' : item => item > 4,
'B' : item => item > 4 && item < 8,
'C' : item => item >8 && item < 15
}
let defaultFilter = item => true
// pick the right filter
let filter = filters[id] || defaultFilter
// now filter the collection with that filter
ar = ar.filter(filter)
With this, you've turned an imperative process of picking the right filter into a declarative process. The filters
object now lists the filters without any logic. This is much more flexible and allows for more future refactoring in other parts of the codebase.
One other tip that might help would be rearrange the argument so that item
is in the middle, and the numbers go from smallest to largest:
item => 4 < item && item < 8
(See this answer for more)
Upvotes: 1
Reputation: 2966
const ar = [1,2,3,4,5,6,7,8,9,10];
const id = "A";
const filtered = {
"A": ar.filter(item => item > 4),
"B": ar.filter(item => item > 4 && item < 8),
"C": ar.filter(item => item >8 && item < 15)
}[id]
console.log(filtered)
Upvotes: 1
Reputation: 74096
You can create a function that will return the filter function, like:
function makeFilterFn(id){
switch (id){
case 'A':
return item => item > 4
case 'B':
return item => item > 4 && item < 8
case 'C':
return item => item > 8 && item < 15
default:
return null
}
}
const filterFn = makeFilterFn(id)
const result = filterFn ? ar.filter(filterFn) : ar
Upvotes: 1