![](/img/trans.png)
[英]Is it possible to filter array values by multiple values by using underscore?
[英]Filter/Reject Array of strings against multiple values using underscore
我想使用下划线使用filters
数组来_.filter
或_.reject
cities
数组。
var cities = ['USA/Aberdeen', 'USA/Abilene', 'USA/Akron', 'USA/Albany', 'USA/Albuquerque', 'China/Guangzhou', 'China/Fuzhou', 'China/Beijing', 'China/Baotou', 'China/Hohhot' ... ]
var filters = ['Akron', 'Albuquerque', 'Fuzhou', 'Baotou'];
到目前为止,我的进度:
var filterList;
if (reject) {
filterList = angular.copy(cities);
_.each(filters, (filter) => {
filterList = _.reject(filterList, (city) => city.indexOf(filter) !== -1);
});
} else {
filterList = [];
_.each(filters, (filter) => {
filterList.push(_.filter(cities, (city) => city.indexOf(filter) !== -1));
});
}
filterList = _.flatten(filterList);
return filterList;
我想对此进行干燥,并在可能的情况下使用更具功能性的方法来实现这一目标?
使用Underscore的更具功能性的版本可能如下所示:
const cities = ['USA/Aberdeen', 'USA/Abilene', 'USA/Akron', 'USA/Albany',
'USA/Albuquerque', 'China/Guangzhou', 'China/Fuzhou',
'China/Beijing', 'China/Baotou', 'China/Hohhot']
const filters = ['Akron', 'Albuquerque', 'Fuzhou', 'Baotou'];
var inList = names => value => _.any(names, name => value.indexOf(name) > -1);
_.filter(cities, inList(filters));
//=> ["USA/Akron", "USA/Albuquerque", "China/Fuzhou", "China/Baotou"]
_.reject(cities, inList(filters));
//=> ["USA/Aberdeen", "USA/Abilene", "USA/Albany",
// "China/Guangzhou", "China/Beijing", "China/Hohhot"]
我在这里使用香草JavaScript(some()和filter()),但我希望你能明白:
const isValidCity = city => filters.some(filter => city.indexOf(filter) > -1)
const filteredCities = cities.filter(isValidCity)
请注意,这是一个循环。 因此,这里的时间复杂度为O(n * m)。
在您的示例中,所有城市键共享相同的模式: country
+ /
+ city
。 您的过滤器均与这些名称的city
部分完全匹配。
如果这是数据中的确定性(可能不是...) ,则可以通过创建一个Map
或object
来存储每个过滤器条目的每个城市,从而减少代码的循环次数:
key
成为您希望过滤器匹配的部分 value
设为原始名称 filters
并在每个键处返回名称。 这种方法总是需要一个数据循环和一个过滤器循环。 对于较小的阵列大小,您不会注意到性能差异。 当其中一个数组的长度为1时,您也不会注意到任何差异。
同样,请注意,这仅在过滤条件和城市之间存在恒定关系时才有效。
var cities = ['USA/Aberdeen', 'USA/Abilene', 'USA/Akron', 'USA/Albany', 'USA/Albuquerque', 'China/Guangzhou', 'China/Fuzhou', 'China/Beijing', 'China/Baotou', 'China/Hohhot' ] var filters = ['Akron', 'Albuquerque', 'Fuzhou', 'Baotou']; const makeMap = (arr, getKey) => arr.reduce( (map, x) => Object.assign(map, { [getKey(x)]: x }), {} ); const getProp = obj => k => obj[k]; const getKeys = (obj, keys) => keys.map(getProp(obj)); // Takes the part after the "/" const cityKey = c => c.match(/\\/(.*)/)[1]; const cityMap = makeMap(cities, cityKey); const results = getKeys(cityMap, filters); console.log(results);
由于您似乎正在使用AngularJS,因此可以利用内置的过滤器功能。 假设city和filter数组同时存在于您的控制器上,并且您正在使用ng-repeat
显示city数组,那么您的控制器上可能会有类似的内容:
function cityFilter(city) {
var cityName = city.split('/')[1];
if (reject) {
return filters.indexOf(cityName) === -1;
} else {
return filters.indexOf(cityName) > -1;
}
}
然后在模板中,您将执行以下操作:
<div ng-repeat="city in cities | filter : cityFilter"></div>
当然,您必须根据代码样式(例如,使用$scope
还是controllerAs
)来稍微修改语法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.