使用underscore.js过滤数组

4

我正在尝试筛选一些对象,以更好地理解JS,并使用underscore.js。

我来自C#背景,习惯于LINQ,但underscore并不完全相同。

您能帮助我根据定义的测试筛选出该数组吗?我遇到的问题是数组上的数组属性。 Where 运算符与C#不同,这通常是我用来过滤项目的。

products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];

it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      //This works but was hoping I could do the mushroom check as well in the same line
      var noNuts = _(products).filter(function (x) { return !x.containsNuts;});

      var noMushrooms = _(noNuts).reject(function(x){ return !_(x.ingredients).any(function(y){return y === "mushrooms";});});


      console.log(noMushrooms);

      var count = productsICanEat.length;
      expect(productsICanEat.length).toBe(count);
  });
4个回答

10

你只需要从 reject 回调函数中删除 !,使其看起来像这样:

var noMushrooms = _(noNuts).reject(function(x){ 
    return _(x.ingredients).any(function(y){return y === "mushrooms";});
});
否则,你会拒绝那些不含蘑菇的食物,而接受那些含有蘑菇的食物。

否则,你会拒绝那些不含蘑菇的食物,而接受那些含有蘑菇的食物。


糟糕!谢谢,这就解决了。有没有想法能否将它串联起来?我已经尝试过了,但没有成功。 - Jon
1
你需要先使用 _.chain(list),然后就可以一整天地链式调用你的函数了 - 就像这样 _.chain(myArray).filter(function(){ }).reject(function(){ }) http://underscorejs.org/#chaining - Thomas Jones
看起来 .any() 已经被弃用了。Underscore 现在有一个 _.some() 方法,根据是否有“一些”匹配项返回 true 或 false。 - skrile
1
@skrile 它并没有被弃用,anysome 的别名。 - JohnnyHK
谢谢@JohnnyHK - 我今天学到了新的东西 :) - skrile

6
一个更简洁的完成方式是使用underscore的chain()函数:
var noMushrooms = _(products).chain()
    .filter(function (x) { 
        return !x.containsNuts;})
    .reject(function(x){ 
        return _(x.ingredients).any(function(y){
            return y === "mushrooms";
        });
    })
    .value();

2
你不需要进行链式操作,但是这种链式操作能够非常清晰地展示你正在对列表进行的操作。 - vegemite4me

4

我设法将我的解决方案全部包装成一个过滤器调用,所以想贴出来:

products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];

 it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      productsICanEat = _(products).filter(function (x) { return !x.containsNuts && !_(x.ingredients).any(function(y){return y === "mushrooms";});});


      expect(productsICanEat.length).toBe(1);
  });

4
这将会得到所期望的结果。
var no_nuts = _.filter(products,function(item) {
         return !item.containsNuts;
       });

var no_mushroom = _.reject(no_nuts,function(item) {
        return _.any(item.ingredients,function(item1) {
            return item1 === "mushrooms"
        }); 
     });

console.log(no_mushroom);

reject()filter()相反,any()等价于数组的某些方法,当通过回调函数传递的数组中的任何元素返回true时,它返回true。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接