【问题标题】:How to process JSON fields with lodash map/countBy/groupBy?如何使用 lodash map/countBy/groupBy 处理 JSON 字段?
【发布时间】:2019-10-23 13:18:00
【问题描述】:

我要处理以下 json:

[
  {
    "id": "device1",
    "name": "dev1",
    "status": "online",
    "pool": "pool1",
    "ports": [
       {
          "id": "port1",
          "status": "online"
       },
       {
          "id": "port2",
          "status": "offline"
       },
       {
          "id": "port3",
          "status": "online"
       }
    ]
  },
  {
    "id": "device2",
    "name": "dev2",
    "status": "online",
    "pool": "pool2",
    "ports": [
       {
          "id": "port1",
          "status": "offline"
       },
       {
          "id": "port2",
          "status": "offline"
       },
       {
          "id": "port3",
          "status": "online"
       }
    ]
  }
]

我需要计算每个池的端口数,我在想这样的事情:

devices.jsx 内部:

fetchDevices(props) {
   Promise.all([
      getDevices()  //=> This func fetchs and return the json
   ]).then(results => {
      let devices = flatten(results)

      if (props.filter) {
        devices = filter(devices, this.props.filter)
      }

      let pools = chain(devices)
         .groupBy('pool')
         .map((value, key) => ({
            name: key,
            devices: chain(value).filter(device => ['online','offline'].includes(device.status)).value()
         }))
         .values()
         .map(pool => Object.assign(pool,
           {
             ports: countBy(pool.devices, 'ports'),
             portsCount: pool.devices.reduce((memo, device) => memo + device.ports, 0)
           })
         )
         .value()
   }
   ...
}

稍后,在代码中我尝试显示 portsCount:

<div><span className="value">{pool.portsCount}</span> {pool.portsCount === 1 ? 'port' : 'ports'}</div>

当我运行代码时,我没有得到任何价值,代码可以吗?还是我在这里遗漏了什么?

基本上我想处理:

var arr = [
{
  "id":"device1",
  "pool":"pool1",
  "ports": [
    {
      "id": "port1",
      "status": "online"
    },
    {
      "id": "port2",
      "status": "offline"
    }
  ]
},
{
  "id":"device2",
  "pool":"pool2",
  "ports": [
    {
      "id": "port1",
      "status": "offline"
    }
  ]
}
];

使用 groupBy 和 .map 获取每个池的 portsCount,有什么想法吗?

【问题讨论】:

  • 你是否将池的值保存到组件的状态,即setState()?否则,您将无法真正呈现它的价值。
  • 请添加最终结果数据结构的示例
  • @AlexanderStaroselsky 是的,我正在保存状态,我认为我的问题是我没有在“端口”字段内循环,这就是为什么我没有得到任何价值
  • 所以最终结果应该是{ pool1: 2, pool2: 1 }?
  • @OriDrori 应该是{ pool1: 2, pool2: 1}

标签: javascript json reactjs lodash


【解决方案1】:

第一个问题是 portsCount 的 reduce 不正确。您没有添加/返回数字,请使用 portslength 属性分别对应 pool

let pools = _.chain(data)
  .groupBy("pool")
  .map((value, key) => ({
    name: key,
    devices: _.chain(value)
      .filter(device => ["online", "offline"].includes(device.status))
      .value()
  }))
  .values()
  .map(pool =>
    Object.assign(pool, {
      ports: _.countBy(pool.devices, "ports"),
      portsCount: pool.devices.reduce((memo, device) => {
        return memo + device.ports.length;
      }, 0)
    })
  )
  .value();

然后在反应代码中你可以像这样循环:

<div>
  {this.state.pools.map(pool => (
    <div>
      <span className="value">{pool.portsCount}</span>{" "}
      {pool.portsCount === 1 ? "port" : "ports"}
    </div>
  ))}
</div>

这里有一个example 正在使用中。

【讨论】:

  • 非常感谢 :) 它也可以这样工作,我只是将 reduce 函数更改为:portsCount: pool.devices.reduce((memo, device) =&gt; memo + device.ports.length, 0) 并且它可以工作,但是......如果我有一个空值,它就不会工作,因为例如: {"id":"device1","pool":"pool1","ports":null}
  • 知道了,我只是添加了一个 if 语句,如果 device.ports 为 null 然后将 "" 分配给它,它可以正常工作:),谢谢大家的回答!
【解决方案2】:
const result = devices.map(device => ({
  [device.pool]: device.ports.length
}))
console.log(result)

https://repl.it/repls/KaleidoscopicLazyBase

【讨论】:

    【解决方案3】:

    GroupBy pool,并将组映射到一个对象。您可以使用 _.flatMap()_.reject() 将组的端口组合到一个数组中,以删除 null 值。要获取组端口的总数,您可以使用_.sumBy()

    const arr = [{"id":"device1","pool":"pool1","ports":[{"id":"port1","status":"online"},{"id":"port2","status":"offline"}]},{"id":"device2","pool":"pool2","ports":[{"id":"port1","status":"offline"}]}, {"id":"device1","pool":"pool1","ports": null}];
    
    const result = _(arr)
      .groupBy('pool')
      .map((g, name) => ({
        name,
        ports: _(g).flatMap('ports').reject(_.isNil).value(), // combine the ports arrays into a single array and remove null values
        portCount: _.sumBy(g, 'ports.length') // count the total ports
      }))
      .value();
    
    console.log(result);
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 2017-02-16
      • 2017-12-30
      • 2016-02-26
      • 1970-01-01
      相关资源
      最近更新 更多