如何按对象数组中的数组属性进行筛选

How to filter by an array property in an array of objects

本文关键字:数组 筛选 属性 何按 对象      更新时间:2023-09-26

我有一个初始化如下的集合:

var invoices = new Array();
var invoice = new Invoice();
invoice.number = "123";
invoice.date = "2016-05-03";
invoice.amount = "100";
var products = new Products();
var product = new Product();
product.code = "A";
product.name = "bar";
products.push(product);   
var product2 = new Product();
product2.code = "B";
product2.name = "foo";
products.push(product2);
invoice.products = products;

现在我要按发票的属性进行筛选,如下所示。

var filtered = invoices.filter(function(invoice){
   return invoice.number == "123";
});

但现在我想得到与编号和产品名称匹配的发票

我该怎么做这个

var filtered = invoices.filter(function(invoice){
   return invoice.number == "123" 
   // && invoice.products "name" == "foo";  //<-- At this level how can I filter?
});

使用Array.some检查是否存在所需名称为的产品

var filtered = invoices.filter(function(invoice){
   return invoice.number == "123" && invoice.products.some(function(prod) {
       return prod.name === 'foo';
   });
});

与使用Array.filter和检查所得阵列的length不同,这完全避免了创建临时阵列和短路;一旦发现命中,就会立即返回true。

var filtered = invoices.filter(function(invoice){
   return invoice.number == "123" && invoice.products.some(function (p) {
      return p.name == "foo";
   });
});

如果您想获得一个新的发票列表,其中包含已筛选的产品,您需要克隆发票,而不是将其与过滤器链接:

    var filtered = []
    invoices.forEach(function (invoice) {
      if (invoice.number != "123") {
        return;
      }
      var newInvoice = new Invoice();
      newInvoice.number = invoice.number;
      newInvoice.date = invoice.date;
      newInvoice.amount = invoice.amount;
      var newProducts = invoice.products.filter(function (product) {
        return product.name == "foo"
      });
      newInvoice.products = newProducts
      filtered.push(newInvoice)
    });

UPD:正如John所说,如果你想通过以下规则过滤发票:"获取所有编号等于123的发票,并且至少有一个名为"foo"的产品,这就是解决方案:

    var filtered = invoices.filter(function(invoice){
       return invoice.number == "123" && invoice.products.some(function (p) {
          return p.name == "foo";
       });
    });