Javascript 使用下划线根据多个值筛选/拒绝字符串数组

Javascript 使用下划线根据多个值筛选/拒绝字符串数组,javascript,functional-programming,underscore.js,Javascript,Functional Programming,Underscore.js,我想使用过滤器或拒绝城市数组,使用过滤器数组使用下划线 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', 'Fu

我想使用
过滤器
拒绝
城市
数组,使用
过滤器
数组使用下划线

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;

如果可能的话,我想干掉这一点,并使用更具功能性的方法来实现这一点?

我在这里使用的是香草JavaScript(some()和filter()),但我希望您能理解:

const isValidCity = city => filters.some(filter => city.indexOf(filter) > -1)

const filteredCities = cities.filter(isValidCity)

请注意,这是一个循环对一个循环。所以这里的时间复杂度是O(n*m)。

因为您似乎在使用AngularJS,所以可以利用内置的过滤器功能。假设控制器上同时存在cities和filters数组,并且您正在使用
ng repeat
显示cities数组,则控制器上可能会有如下内容:

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>
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"]


当然,您必须根据您的代码样式稍微修改语法(例如,您是使用
$scope
还是
controllerAs
)。

使用下划线的功能性更强的版本可能如下所示:

<div ng-repeat="city in cities | filter : cityFilter"></div>
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"]

在您的示例中,所有城市密钥共享相同的模式:
country
+
/
+
city
。您的过滤器都与这些名称的
城市
部分完全匹配

如果您的数据中确定了这一点(可能不是…),您可以通过创建每个过滤器条目存储每个城市的
地图
对象
来减少代码的循环次数:

  • 为每个城市名称创建一个带有条目的对象
  • 使
    成为您希望过滤器匹配的部分
  • 值设置为原始名称
  • 循环通过
    过滤器
    ,并返回每个键的名称
这种方法总是需要一个循环通过数据,一个循环通过过滤器。对于较小的阵列大小,您不会注意到性能差异。当其中一个数组的长度为1时,您也不会注意到任何差异

再次,请注意,只有当过滤器和城市之间存在恒定关系时,这才有效

var cities=[“美国/阿伯丁”,“美国/阿比林”,“美国/阿克伦”,“美国/奥尔巴尼”,“美国/阿尔伯克基”,“中国/广州”,“中国/福州”,“中国/北京”,“中国/包头”,“中国/呼和浩特”]
var过滤器=[‘阿克伦’、‘阿尔伯克基’、‘福州’、‘包头’];
const makeMap=(arr,getKey)=>arr.reduce(
(map,x)=>Object.assign(map{
[getKey(x)]:x
}), {}
);
常量getProp=obj=>k=>obj[k];
常量getKeys=(obj,keys)=>keys.map(getProp(obj));
//取“/”后面的部分
const cityKey=c=>c.match(/\/(.*)/)[1];
const cityMap=makeMap(cities,cityKey);
const results=getKeys(城市地图、过滤器);

控制台日志(结果)返回过滤器.map(el=>“USA/”+el);为什么城市的格式在
城市
过滤器
之间有所不同?如果不是这样,您可以大大简化代码。
过滤器是用户输入。
城市
是来自API的数据。所以,我正在尝试适应更灵活的过滤。谢谢你的回答。这是服务中的一个函数,不使用ng repeat。使用角度过滤器也不是一个选项。我不太喜欢这种方法?我一直收到
filteredCities===cities
抱歉,修复了索引。如果你能解释一下你是如何来到这里的,那就太棒了?你的思维过程?再次感谢dude:)复杂性实际上是
O(m*n)
(最坏的情况是,由于短路,在平均情况下更好。)