Reputation: 3195
I have a object containing the following:
assets = [
{ id: 1, type: 'image', url: 'image.jpg' },
{ id: 2, type: 'video', url: 'video.mp4' },
]
I'd like to filter based on user selection of IMAGE, VIDEO, or ALL.
I cannot think of a clean way to filter use for the ALL case.
currentOption = 'image'
assets.filter(asset => asset.type === currentOption)
This will work for IMAGE or VIDEO, but not ALL.
I could check in my filter function:
const currentOption = 'all'
const filterFunc = asset => {
if (currentOption == 'all') return true
return asset.type === currentOption
}
assets.filter(filterFunc)
But wouldn't it be better to short-circuit the filter to not iterate each item?
Edit: To answer questions why not skip filter all together. I was trying to keep it framework agnostic. But this is rendered using react. So I would have to do something like:
<div>
{currentOption === 'all' ?
assets.map(asset =>
<img src={asset.url} />
)
:
assets.filter(asset => asset.type === currentOption).map(asset =>
<img src={asset.url} />
)
}
</div>
Plus this doesn't even account for the code to display a video. Basically I was trying to reduce duplication in the view code.
Upvotes: 16
Views: 42746
Reputation: 8459
This might work for you:
assets.map(
filter(
asset {
return !currentOption ? asset : asset.type === currentOption
}
)
You could go a step further and declare an 'all' current option if you think that would be more explicit.
Hope it helps!
Upvotes: 0
Reputation: 351369
You could use the ternary operator to decide whether or not to apply the filter:
currentOption === 'all' ? assets : assets.filter(asset => asset.type === currentOption)
The mapping to images, that you added to the end of your question, could be written like this:
(currentOption === 'all' ? assets : assets.filter(asset => asset.type === currentOption))
.map( asset => <img src={asset.url} /> )
Upvotes: 14
Reputation: 390
I would go with what you suggested, more or less:
assets.filter(asset => currentOption === "all" || asset.type === currentOption);
Keep in mind that filter() iterates over all of the items anyway.
Upvotes: 6
Reputation: 8075
You can do something like this:
let currentOption = null; //or 'image', or 'video'
const new_assets =
assets.filter(asset => !currentOption || asset.type === currentOption)
set currentOption to null if you don't want to filter, or if set it to anything, consider to do the comparison. But as said before, filter() will iterate over the entire array. It will be more wise to check the currentOption before, if it is 'all' you can just copy the array.
Upvotes: -3