简体   繁体   English

Javascript:使用reduce / map等创建具有特定值的对象数组

[英]Javascript: Create array out array of objects with certain value using reduce / map etc

I want to create an array of objects from an array of objects, this is the data: 我想从一个对象数组创建一个对象数组,这是数据:

// Input:
const shippingMethodOptions = [{
  id: 1,
  carrier_token: 'fedex',
  carrier_name: 'Fedex',
  weight: 1,
  price: 3
}, {
  id: 2,
  carrier_token: 'fedex',
  carrier_name: 'Fedex',
  weight: 2,
  price: 6
}, {
  id: 3,
  carrier_token: 'fedex',
  carrier_name: 'Fedex',
  weight: 6,
  price: 9
}, {
  id: 4,
  carrier_token: 'usps',
  carrier_name: 'Usps',
  weight: 6,
  price: 9
}, {
  id: 5,
  carrier_token: 'delaware',
  carrier_name: 'Delaware',
  weight: 5,
  price: 10
}]

As you can see the data has carrier_token and carrier_name , what I want is to create an output array with the unique carriers like so: 正如您所看到的,数据有carrier_tokencarrier_name ,我想要的是创建一个具有唯一carriers的输出数组,如下所示:

// Output:
const carriers = [{
  carrier_token: 'fedex',
  carrier_name: 'Fedex'
}, {
  carrier_token: 'usps',
  carrier_name: 'USPS'
}, {
  carrier_token: 'delaware',
  carrier_name: 'Delaware'
}]

What I have tried is building it with a for loop, however I would love to know if this is possible in a more clean way (reduce?) 我试过用for循环构建它,但是我想知道这是否可能以更干净的方式(减少?)

This is my current solution so far (but again, I would love to know if it's possible to make it cleaner with Reduce etc.) 这是我目前的解决方案(但同样,我很想知道是否可以通过Reduce等使其更清洁)

const getCarriers = options => {
  const carriers = []

  options.forEach(({ carrier_token, carrier_name }) => {
    const foundIndex = _.findIndex(carriers, carrier => carrier.carrier_token === carrier_token)

    if (foundIndex !== -1) {
      return
    }

    carriers.push({
      carrier_token,
      carrier_name
    })
  })

  return carriers
}

const carriers = getCarriers(shippingMethodOptions)

Seems like a pretty straight-forward reduce job. 看起来像一个非常简单的减少工作。

What you'll need is a way to keep track of existing carriers. 您需要的是一种跟踪现有运营商的方法。 I recommend using a Set and storing keys made from the token and name, for example in a string like "<token>:<name>" . 我建议使用Set和存储由令牌和名称创建的密钥,例如在"<token>:<name>"类的字符串中。

 const shippingMethodOptions = [{"id":1,"carrier_token":"fedex","carrier_name":"Fedex","weight":1,"price":3},{"id":2,"carrier_token":"fedex","carrier_name":"Fedex","weight":2,"price":6},{"id":3,"carrier_token":"fedex","carrier_name":"Fedex","weight":6,"price":9},{"id":4,"carrier_token":"usps","carrier_name":"Usps","weight":6,"price":9},{"id":5,"carrier_token":"delaware","carrier_name":"Delaware","weight":5,"price":10}] const carriers = shippingMethodOptions.reduce(function(arr, smo) { let key = `${smo.carrier_token}:${smo.carrier_name}` return this.has(key) ? arr : this.add(key) && arr.concat({ carrier_token: smo.carrier_token, carrier_name: smo.carrier_name }); }.bind(new Set()), []) console.info(carriers) 

I'm binding the Set to the reduce callback so it can be used via the this keyword however you could just as easily create it outside the callback scope and store it in a variable, eg 我将Set绑定到reduce回调,因此可以通过this关键字使用它,但是您可以在回调范围之外轻松创建它并将其存储在变量中,例如

const keys = new Set()

I'd consider using .reduce() with a Map() , where the map entries have keys based on ${carrier_token}:${carrier_name} and values in the required object format. 我考虑将.reduce()Map() ,其中映射条目具有基于${carrier_token}:${carrier_name}和所需对象格式的值。 Then use Array.from() on the .values() of the map. 然后使用Array.from().values()的地图。

 const shippingMethodOptions = [{"id":1,"carrier_token":"fedex","carrier_name":"Fedex","weight":1,"price":3},{"id":2,"carrier_token":"fedex","carrier_name":"Fedex","weight":2,"price":6},{"id":3,"carrier_token":"fedex","carrier_name":"Fedex","weight":6,"price":9},{"id":4,"carrier_token":"usps","carrier_name":"Usps","weight":6,"price":9},{"id":5,"carrier_token":"delaware","carrier_name":"Delaware","weight":5,"price":10}] const carriers = Array.from( shippingMethodOptions.reduce((map, {carrier_token, carrier_name}) => { const key = `${carrier_token}:${carrier_name}` if (!map.has(key)) map.set(key, { carrier_token, carrier_name }) return map }, new Map()).values() ) console.log(carriers) 

Or if just the carrier_token is enough for uniqueness you can simplify it: 或者,如果只有carrier_token足以实现唯一性,您可以简化它:

 const shippingMethodOptions = [{"id":1,"carrier_token":"fedex","carrier_name":"Fedex","weight":1,"price":3},{"id":2,"carrier_token":"fedex","carrier_name":"Fedex","weight":2,"price":6},{"id":3,"carrier_token":"fedex","carrier_name":"Fedex","weight":6,"price":9},{"id":4,"carrier_token":"usps","carrier_name":"Usps","weight":6,"price":9},{"id":5,"carrier_token":"delaware","carrier_name":"Delaware","weight":5,"price":10}] const carriers = Array.from( shippingMethodOptions.reduce((map, {carrier_token, carrier_name}) => { if (!map.has(carrier_token)) map.set(carrier_token, { carrier_token, carrier_name }) return map }, new Map()).values() ) console.log(carriers) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM