如何动态过滤对象?

时间:2015-04-04 11:32:15

标签: javascript arrays javascript-objects

我有一个Javascript数组:

var peoples = [  
{'people':{'sex':'male', 'diet':'vegetarian','favPlaces':['place1','place2']}},  
{'people':{'sex':'female', 'diet':'flexitarian','favPlaces':['place2','place3']}},  
{'people':{'sex':'male', 'diet':'flexitarian', 'favPlaces':['place4','place1']}}  
];

如果我选择 {' sex':['女性'男性']}&& {'饮食':[' flexitarian']} 输出应为 [' place2',& #39; place3',' place4',' place1']

我的代码存在的问题是,如果我只选择'性别' ,它将无法显示结果,但如果我同时选择'性别' '饮食' 它会显示结果。 我无法弄清楚如何使我的代码动态化,以便当我选择性别或饮食或性别和饮食时代码将动态过滤,他们将显示结果。

这是我的代码:

 var filterObj = {'sex': ['female', 'male'], 'diet': ['flexitarian']};

    for(var p in peoples){  
       for(var s in filterObj.sex){  
          for(var d in filterObj.diet){
          if((filterObj.sex[s] == peoples[p].people.sex) && (filterObj.diet[d] == peoples[p].people.diet)){  
            console.log(peoples[p].people.favPlaces);
           }
       }  
    }  

这是HTML:

<ul id="sex">
<li><label><input type="checkbox" value="male">Male</label></li>
<li><label><input type="checkbox" value="female">Female</label></li>
</ul>
<ul id="diet">
<li><label><input type="checkbox" value="none">None</label></li>
<li><label><input type="checkbox" value="flexitarian">Flexitarian</label></li>
<li><label><input type="checkbox" value="vegetarian">Vegetarian</label></li>
</ul>

2 个答案:

答案 0 :(得分:1)

您可以使用Array.indexOf并反转条件,例如...检查是否可以在条件中找到个别数据,但如果没有任何内容(通过检查其长度)也忽略过滤器,如下所示...

var matchingSet = peoples.filter(function(p) {
    return (filterObj.sex.length === 0 || filterObj.sex.indexOf(p.people.sex) !== -1)     //peoples' sex must exists in the filter.sex or ignore it if filter not specified
    && (filterObj.diet.length === 0 || filterObj.diet.indexOf(p.people.diet) !== -1);     //and people's diet must exists in the filter.diet or ignore it if filter not specified
});

之后,使用Array.map从匹配集中拉出favPlaces。

var matchingPlaces = matchingSet.map(function(p) { return p.people.favPlaces; });

最后,使用Underscore(比制作自己的更容易,因为我认为没有原生的JavaScript数组方法可用于...展平,从favPlaces数组中提取唯一值并对其进行排序(作为额外奖励):

var flatten = _.chain(matchingPlaces)
    .flatten()
    .uniq()
    .sortBy(function(p) { return p; })
    .value();

这将为您提供您正在寻找的结果。

["place1","place2","place3","place4"]

完整示例可在以下网址找到:http://jsfiddle.net/rdfyp5c9/2/

请注意,在示例中,我删除了饮食过滤元素:

var filterObj = {
    'sex' : ['male'],
    'diet': []
};

并且正确返回

["place1","place2","place4"]

结果。

你绝对可以在matchingSet分配行中改进过滤器,以检查是否filterObj.sex不是真实的,只检查它是否是数组等长度检查,但为了保持简单......这个特殊的解决方案假设如果你不想在过滤器中饮食,那么就需要将空阵列作为饮食......

答案 1 :(得分:0)

使用开源项目jinqJs应该很容易

var peoples = [  
{'people':{'sex':'male', 'diet':'vegetarian','favPlaces':['place1','place2']}},  
{'people':{'sex':'female', 'diet':'flexitarian','favPlaces':['place2','place3']}},  
{'people':{'sex':'male', 'diet':'flexitarian', 'favPlaces':['place4','place1']}}  
];

var result = jinqJs().from(peoples).where(function(row){return (row.people.sex === 'female' || row.people.diet === 'flexitarian');}).select(function(row){return row.people.favPlaces;});

document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 4) + '</pre><br><br>';
<script src="https://rawgit.com/fordth/jinqJs/master/jinqjs.js"></script>