- Lo-Dash Essentials
- Adam Boduch
- 1150字
- 2021-08-06 19:27:37
Searching for data
Applications don't use entire collections. Rather, they iterate over a collection subset, or they look for a specific item in the collection. Lo-Dash has a number of functional tools to help the programmer find the data they need.
Filtering collections
The simplest way to perform a filter operation on a collection using Lo-Dash is to use the where()
function. This function takes an object argument and will match its properties against each item in the collection, as shown in the following code:
var collection = [ { name: 'Moe', age: 47, gender: 'm' }, { name: 'Sarah', age: 32, gender: 'f' }, { name: 'Melissa', age: 32, gender: 'f' }, { name: 'Dave', age: 32, gender: 'm' } ]; _.where(collection, { age: 32, gender: 'f' }); // → // [ // { name: "Sarah", age: 32, gender: "f" }, // { name: "Melissa", age: 32, gender: "f" } // ]
The preceding code filters the collection on both the age
and the gender
properties. The query translates to thirty-two year old females. The Moe
object matches with neither property, while the Dave
object matches with the age
property, but not gender
. A good way to think about where()
filtering is that each object property you pass in as the filter will be logical and joined together. For example, match the age
and the gender
properties.
The where()
function is great for its concise syntax and intuitive application to collections. With this simplicity comes a few limitations. First, the property values that we're comparing to each item in the collection must match exactly. Sometimes, we need comparisons a little more exotic than strict equality. Second, the logical and
way that where()
joins query conditions together isn't always desirable. Logical or
conditions are just as common.
For these types of advanced filtering capabilities, you should turn to the filter()
function. Here's a basic filter operation that's even simpler than the where()
queries:
var collection = [ { name: 'Sean', enabled: false }, { name: 'Joel', enabled: true }, { name: 'Sue', enabled: false }, { name: 'Jackie', enabled: true } ]; _.filter(collection, 'enabled'); // → // [ // { name: "Joel", enabled: true }, // { name: "Jackie", enabled: true } // ]
Since the enabled
property has truthy values for two objects in this collection, they're returned in a new array.
Note
Lo-Dash uses the notion of truthy values everywhere. This simply means that a value will test positive if used in an if
statement or a ternary operator. Values don't need to be of Boolean type and true
to be truthy. An object, an array, a string, a number—these are all truthy values. Whereas null, undefined, and 0— are all false.
As mentioned, the filter()
function fills gaps in the where()
function. Unlike where()
,filter()
accepts a callback function that's applied to each item in the collection, as shown in the following code:
var collection = [ { type: 'shirt', size: 'L' }, { type: 'pants', size: 'S' }, { type: 'shirt', size: 'XL' }, { type: 'pants', size: 'M' } ]; _.filter(collection, function(item) { return item.size === 'L' || item.size === 'M'; }); // → // [ // { type: "shirt", size: "L" }, // { type: "pants", size: "M" } // ]
The callback function uses an or
condition to satisfy the size
constraint here—medium
or large
. This is simply not doable with the where
function.
Filtering collections using the filter()
function is good when we know what we're looking for. The callback function gives the programmer enough flexibility to compose elaborate criteria. But sometimes, we don't know what you need from a collection. Instead, you only know what you don't need, as shown in the following code:
var collection = [ { name: 'Ryan', enabled: true }, { name: 'Megan', enabled: false }, { name: 'Trevor', enabled: false }, { name: 'Patricia', enabled: true } ]; _.reject(collection, { enabled: false }); // → // [ // { name: "Ryan", enabled: true }, // { name: "Patricia", enabled: true } // ]
You can see here that only enabled
items are returned that are equivalent to doing _.filter(collection, {enabled: true})
,which is a simple inversion of filter()
. Which function you use is a matter of personal preference and the context in which they're used. Go for the one that reads cleaner in your code.
Finding items in collections
Sometimes, we need a specific collection item. Filtering a collection simply generates a new collection with less items in it. Conversely, finding items in a collection means finding a specific item.
The function used to find items in a collection is aptly named find()
. This function accepts the same arguments as the filter()
function. You can pass the name of the property as a string, an object filled with property names and values to execute a where style search, or just a plain callback function to match against whatever you want. The following is an example of this:
var collection = [ { name: 'Derek', age: 37 }, { name: 'Caroline', age: 35 }, { name: 'Malcolm', age: 37 }, { name: 'Hazel', age: 62 } ]; _.find(collection, { age:37 }); // → { name: "Derek", age: 37 }
There're actually two items matching this where style criteria in the collection—Derek
and Malcolm
. If we were to run this code though, we'd see that only Derek
is returned. That's because find()
returns as soon as a match is found. Collection order matters when searching for items in collections. It doesn't take into consideration duplicate values.
Let's look in the other direction and see what we find. Using the same collection and the same search criteria, you can search in the opposite direction:
_.findLast(collection, { age:37 }); // → { name: "Malcolm", age: 37 }
While find()
searches for the first occurrence of the matching item in the collection, findLast()
searches for the last occurrence. This is useful when we're working with sorted collections—you can better optimize your linear searches.
Note
While Lo-Dash heavily optimizes the while
loops used when iterating over collections, searches executed using functions such as find()
are linear. It's important to remember that it's up to the programmer using Lo-Dash to consider the performance implications of their unique application data. Lo-Dash functions are optimized for the generic common case, they're not going to magically make your code faster by virtue of using them. They're tools to assist the programmer to make incredibly high-performance code.