Javascript:按过滤器对象列表过滤对象列表

时间:2018-04-06 08:51:19

标签: javascript reactjs ecmascript-6

我目前有两个不同的对象列表,一个需要过滤另一个。这是他们目前的样子。

var heroes = [
    {
      name: "warrior",
      primary_skill: "greater bash",
      attack_type: "melee",
      attribute: "strength"
    },
    {
      name: "ranger",
      primary_skill: "focus fire",
      attack_type: "range",
      attribute: "agility"
    },
    {
      name: "mage",
      primary_skill: "oblivion",
      attack_type: "magic",
      attribute: "intelligence"
    },
    {
      name: "soldier",
      primary_skill: "sword dance",
      attack_type: "melee",
      attribute: "strength"
    }
]

应通过以下

过滤
var filters = [
    { attack_type: "melee" },
    { attribute: "strength" }
]

过滤器应该以“和”方式工作,因此这将过滤英雄列表,以便只显示具有strength属性的近战英雄。

这是我到目前为止的尝试,但我没有取得多大进展:

const filteredHeroes = heroes.filter(
    hero => {
        return filters.some( 
            filter => {
                return filter.attack_type === hero.attack_type &&
                filter.primary_skill === hero.primary_skill &&
                filter.attribute === hero.attribute
            }
        )
    }
)

我理解这个过滤器功能毫无意义..但我不知道正确的方法来做我需要的。

理想情况下,应用过滤器的函数与所包含的属性无关,因此,如果数据集包含当前不存在的新属性,则filters数组可以接受该属性以及应用它们的函数不需要任何更新。

我不希望包含任何外部库,向后兼容性不是一个大问题 - 只要它适用于IE11和所有其他现代浏览器。

3 个答案:

答案 0 :(得分:8)

使用filterevery

heroes.filter( s => //for every object in heroes
    filters.every( t => { //check if every filter in iteration has the same value or not
       var key = Object.keys(t)[0]; 
       return s[key] == t[key]
    })
);

<强>演示

var heroes = [{
    name: "warrior",
    primary_skill: "greater bash",
    attack_type: "melee",
    attribute: "strength"
  },
  {
    name: "ranger",
    primary_skill: "focus fire",
    attack_type: "range",
    attribute: "agility"
  },
  {
    name: "mage",
    primary_skill: "oblivion",
    attack_type: "magic",
    attribute: "intelligence"
  },
  {
    name: "soldier",
    primary_skill: "sword dance",
    attack_type: "melee",
    attribute: "strength"
  }
];
var filters = [{
    attack_type: "melee"
  },
  {
    attribute: "strength"
  }
];

var output = heroes.filter(s => filters.every(t => {
  var key = Object.keys(t)[0];
  return s[key] == t[key]
}));

console.log(output);

对于IE11兼容性,使用普通函数(不使用箭头函数)和every var output = heroes.filter( function(s){ return filters.every( function(t) { var key = Object.keys(t)[0]; return s[key] == t[key] }); });

whereBetween

答案 1 :(得分:2)

我认为您的数据结构并未真正适用,filters应该是对象而不是数组:

&#13;
&#13;
const heroes = [
    {
      name: "warrior",
      primary_skill: "greater bash",
      attack_type: "melee",
      attribute: "strength"
    },
    {
      name: "ranger",
      primary_skill: "focus fire",
      attack_type: "range",
      attribute: "agility"
    },
    {
      name: "mage",
      primary_skill: "oblivion",
      attack_type: "magic",
      attribute: "intelligence"
    }
 ];

const filters = { attack_type: "melee", attribute: "strength" };

const filteredHeroes = heroes.filter(hero => 
   Object.keys(filters).every(key => hero[key] === filters[key])
);
 
 console.log(filteredHeroes);
&#13;
&#13;
&#13;

答案 2 :(得分:0)

这种方式也有效

var output =  heroes.filter(function(hero) {
return hero.attribute == 'strength'&&hero.attack_type== 'melee' ;   


 });

&#13;
&#13;
var heroes = [{
    name: "warrior",
    primary_skill: "greater bash",
    attack_type: "melee",
    attribute: "strength"
  },
  {
    name: "ranger",
    primary_skill: "focus fire",
    attack_type: "range",
    attribute: "agility"
  },
  {
    name: "mage",
    primary_skill: "oblivion",
    attack_type: "magic",
    attribute: "intelligence"
  },
  {
    name: "soldier",
    primary_skill: "sword dance",
    attack_type: "melee",
    attribute: "strength"
  }
];

var output =  heroes.filter(function(hero) {
	return hero.attribute == 'strength'&&hero.attack_type== 'melee' ;	
  

});


console.log(output);
&#13;
&#13;
&#13;