通过使用_.reduce

时间:2018-08-08 10:25:35

标签: javascript underscore.js

我需要从现有数组中提取数据,以仅过滤数量为reference_id的每个项目的年份和> 0

我的sample_array包含以下数据:

var sample_array = [{
    'reference_id': 1,
    'products': [{
        year: 1,
        quantity: 0
    }, {
        year: 2009,
        quantity: 5
    }]
}, {
    'reference_id': 2,
    'products': [{
        year: 2009,
        quantity: 0
    }]
}, {
    'reference_id': 3,
    'products': [{
        year: 1,
        quantity: 0
    }, {
        year: 2009,
        quantity: 5
    }]
}, {
    'reference_id': 4,
    'products': [{
        year: 2014,
        quantity: 10
    }, {
        year: 2015,
        quantity: 6
    }]
}];

为了让我提取所需数据的方式,我两次使用_.each(在少数项目中仍使用 underscore.js )先进行过滤,然后重新构建yearreference_id组成的数组。

var references = [];

_.each(sample_array, function(reference) {
    reference_products = _.filter(reference.products, function(data) {
        return data.quantity > 0;
    });
    if (!_.isEmpty(reference_products))
        _.each(reference_products, function(product) {
            references.push({
                'reference_id': reference.reference_id,
                'year': product.year
            });
        });
});

它可以正常工作,但是我认为使用_.reduce购买数组引用可能是一种更为优雅的方法,但是我没有找到实现它的方法。

预期的结果将是console.log(references)

[{
    reference_id: 1
    year: 2009
} {
    reference_id: 3
    year: 2009
} {
    reference_id: 4
    year: 2014
} {
    reference_id: 4
    year: 2015
}]

任何提示吗?

2 个答案:

答案 0 :(得分:3)

reduce将不必要地使代码复杂化,因为您必须手动收集结果。取而代之的是,您可以通过map对数组进行平移来创建仅包含所需值的中间数组,然后对其进行展平来表示这一点:

var sample_array = [{
  'reference_id': 1,
  'products': [{
    year: 1,
    quantity: 0
  }, {
    year: 2009,
    quantity: 5
  }]
}, {
  'reference_id': 2,
  'products': [{
    year: 2009,
    quantity: 0
  }]
}, {
  'reference_id': 3,
  'products': [{
    year: 1,
    quantity: 0
  }, {
    year: 2009,
    quantity: 5
  }]
}, {
  'reference_id': 4,
  'products': [{
    year: 2014,
    quantity: 10
  }, {
    year: 2015,
    quantity: 6
  }]
}];

const combined = _.map(
  sample_array,
  (e) =>                        // for each first-level element...
    _.chain(e.products)         // look at its `products` array...
    .filter((p) => p.quantity > 0) // keeping only those with a quantity > 0
    .map((p) => {                  // and now return the result of mapping over that array of products
      return {
        reference_id: e.reference_id,
        year: p.year
      };
    })
    .value());

console.log(combined);

// the above value is an array of arrays (one per first-level
// element), so we need to flatten it
const references = _.flatten(combined, true);

console.log(references);

(我在转换函数内部使用了_.chain,以使流程更清晰。)

答案 1 :(得分:1)

这是我使用reducefiltermap解决问题的另一种方法。

const references = [{
    'reference_id': 1,
    'products': [{
        year: 1,
        quantity: 0
    }, {
        year: 2009,
        quantity: 5
    }]
}, {
    'reference_id': 2,
    'products': [{
        year: 2009,
        quantity: 0
    }]
}, {
    'reference_id': 3,
    'products': [{
        year: 1,
        quantity: 0
    }, {
        year: 2009,
        quantity: 5
    }]
}, {
    'reference_id': 4,
    'products': [{
        year: 2014,
        quantity: 10
    }, {
        year: 2015,
        quantity: 6
    }]
}];

const result = references.reduce((acc, reference) => {
  const { reference_id, products } = reference;
  const productsWithQuantity = products.filter(product => product.quantity > 0);
  const productsWithReference = productsWithQuantity.map(product => ({ reference_id: reference_id, year: product.year}));
  
  return [...acc, ...productsWithReference];
}, []);

console.log(result);