【问题标题】:Convert nested array of objects to object of key-value pairs using reducer使用 reducer 将嵌套的对象数组转换为键值对对象
【发布时间】:2020-05-30 00:06:35
【问题描述】:

我有一个如下所示的可观察输出。我想将此数据转换为所需的格式(如下提供)。我部分成功地形成了键值对,但不知道如何只将一个字段(即 selected 为 true)从汽车数组发送到最终输出。

***可观察的输出****

[{
  "name":"John",
  "age":30,
  "cars": [
      { "selected":true,  "name":"Ford", "models": "Mustang"},
      { "selected":false, "name":"BMW", "models": "320" },
      { "selected":true, "name":"Fiat", "models":"500" }
  ]
 },
 {
  "name":"alex",
  "age":40,
  "cars": [
      { "selected":true,  "name":"tesla", "models": "x"},
      { "selected":false, "name":"merc", "models": "300" },
      { "selected":true, "name":"honda", "models":"accord" }
   ]
  }
]

****所需格式*****

{John:[ford, fiat], Alex:[tesla,honda]} 

***使用的代码*****

const results = item.reduce((r,{name,cars}) => (r[name]=cars,r), {})

//这给了我完整的汽车对象,但我只需要从中命名(对于选定的真实对象也是如此)。

编辑1:不想在最终对象中有空记录。例如,如果 Alex 没有任何 Cars Selected True 那么我不希望 Alex:[] 在最终对象中。

【问题讨论】:

  • const results = data.reduce((r,{name,cars}) => (r[name]=cars.filter(ch => ch.selected).map(ch => ch.name),r), {}); 可能是这样的?
  • @Halili Cakar。谢谢,这就像一个魅力。如果我只想在至少有一个值的情况下返回 'r' 怎么办。例如,在上面的 Alex 示例中,如果没有一辆车选择 true,那么结果不应该有 Alex 记录。
  • 嘿@Raji 我很高兴它对你有用。如果您想过滤只有汽车的结果,您可能想先过滤并再次使用此功能减少它。所以试试这个; data.filter(ch => ch.cars.some(car => car.selected)).reduce((r,{name,cars}) => (r[name]=cars.filter(ch => ch.selected).map(ch => ch.name),r), {})

标签: javascript arrays rxjs


【解决方案1】:

这个 sn-p 会有所帮助

 const array = [{
  "name":"John",
  "age":30,
  "cars": [
      { "selected":true,  "name":"Ford", "models": "Mustang"},
      { "selected":false, "name":"BMW", "models": "320" },
      { "selected":true, "name":"Fiat", "models":"500" }
  ]
 },
 {
  "name":"alex",
  "age":40,
  "cars": [
      { "selected":true,  "name":"tesla", "models": "x"},
      { "selected":false, "name":"merc", "models": "300" },
      { "selected":true, "name":"honda", "models":"accord" }
   ]
  }
]


const newArray = array.reduce((acc, rec) => {
  const cars = rec.cars.filter(c => c.selected)

  return cars.length ? {...acc, [rec.name]: cars.map(c => c.name)} : acc
}, {})

console.log(newArray)

【讨论】:

    【解决方案2】:

    使用forEach 并构建一个对象

    更新:使用reduce的另一个解决方案

    data = [
      {
        name: "John",
        age: 30,
        cars: [
          { selected: true, name: "Ford", models: "Mustang" },
          { selected: false, name: "BMW", models: "320" },
          { selected: true, name: "Fiat", models: "500" },
        ],
      },
      {
        name: "alex",
        age: 40,
        cars: [
          { selected: false, name: "tesla", models: "x" },
          { selected: false, name: "merc", models: "300" },
          { selected: false, name: "honda", models: "accord" },
        ],
      },
    ];
    
    
    const output = data.reduce((acc, { name, cars }) => {
      const items = cars.filter(({selected}) => selected).map(({name}) => name);
      if (items.length > 0) {
         acc[name] = items;
      }
      return acc;
    }, {});
    
    console.log(output);

    【讨论】:

    • 感谢您。但我的问题是使用减速器来实现这一点。
    • @Raji,当然,使用reduce 更新了答案。我认为在这里使用 forEach 会很简单。
    • 非常感谢您的更新。所有这些都很好,但我不希望最终对象中有空记录。例如,在上面的 Alex 示例中,如果没有一辆车选择 true,则 OUTPUT 不应该有 Alex 记录。我尝试添加几个条件,但随后我丢失了以前存储的数据。你也可以帮忙吗?
    • 更新了处理上述案例的答案。
    • 感谢您的回复。这对我来说是完整的答案。所以接受它。
    猜你喜欢
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多