Reputation: 121
I have the following json to process:
[
{
"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"
}
]
}
]
And I need to count the number of ports for each pool, I was thinking about something like this:
inside 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()
}
...
}
Later, on the code I try to display the portsCount:
<div><span className="value">{pool.portsCount}</span> {pool.portsCount === 1 ? 'port' : 'ports'}</div>
when I run the code I'm getting no value at all, is the code ok? or am I missing something here?
basically I want to process:
var arr = [
{
"id":"device1",
"pool":"pool1",
"ports": [
{
"id": "port1",
"status": "online"
},
{
"id": "port2",
"status": "offline"
}
]
},
{
"id":"device2",
"pool":"pool2",
"ports": [
{
"id": "port1",
"status": "offline"
}
]
}
];
and with groupBy and .map get the portsCount for each pool, any ideas?
Upvotes: 0
Views: 610
Reputation: 38787
The first issue is that the reduce for portsCount
is not correct. You aren't adding/returning a number, use the length
property of ports
for that respective 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();
Then in the react code you can loop over like this:
<div>
{this.state.pools.map(pool => (
<div>
<span className="value">{pool.portsCount}</span>{" "}
{pool.portsCount === 1 ? "port" : "ports"}
</div>
))}
</div>
Here is an example in action.
Upvotes: 1
Reputation: 191976
GroupBy the pool
, and map the the groups to an object. You can combine the groups' ports to an array using _.flatMap()
with _.reject()
to remove null
values. To get the total count of the groups' ports you can use _.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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Upvotes: 1
Reputation: 474
const result = devices.map(device => ({
[device.pool]: device.ports.length
}))
console.log(result)
https://repl.it/repls/KaleidoscopicLazyBase
Upvotes: 1