【问题标题】:How to filter by an array property in an array of objects如何按对象数组中的数组属性进行过滤
【发布时间】:2016-08-28 22:38:40
【问题描述】:

我有一个这样初始化的集合:

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?
});

【问题讨论】:

    标签: javascript arrays object filter


    【解决方案1】:

    使用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。

    【讨论】:

    • 注意:我还在some回调中使用了安全的非类型强制===相等检查;理想情况下,您应该在检查number 时在filter 回调中执行相同的操作。我没有修复的唯一原因是它实际上被命名为number,我担心某些代码可能会将其分配为Number,而其他代码可能会分配给string,因此可能需要类型强制;使用一致的类型并使用非强制相等检查; coercive equality is one of the "bad parts" in JavaScript 考虑到它可能是多么不一致/不直观。
    【解决方案2】:
    var filtered = invoices.filter(function(invoice){
       return invoice.number == "123" && invoice.products.some(function (p) {
          return p.name == "foo";
       });
    });
    

    【讨论】:

    • 很好的解决方案,但不仅仅是发布代码,最好对您的答案进行解释,以便 OP 一定能理解它。
    【解决方案3】:

    如果您想获取包含过滤产品的新发票列表,您需要克隆发票,而不是将它们与过滤器链接:

        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";
           });
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 2021-11-25
      • 2020-01-20
      • 2019-08-22
      • 2019-07-17
      • 1970-01-01
      相关资源
      最近更新 更多