I have a function which it iterate through an arrays to return a value base on condition. I used these:
export const DeviceCount = ({ home }: IDeviceCount) => {
let sensorCount = 0;
let hubcount = 0;
if (home.rooms && home.rooms.length)
home?.rooms.forEach(
(home) =>
home.nodes &&
home?.nodes.forEach((node) => {
if (["11", "12", "13", "14", "15"].includes(node?.type))
sensorCount ;
else hubcount ;
})
);
return { sensorCount, hubcount };
};
I was looking for a better way for iterate through arrays .Because the above method is annoying.
But I want a better method.
thanks and regards
CodePudding user response:
If you can use optional chaining, then one of the bigger benefits of it is to access a possibly undefined nested property directly instead of testing if it exists first. Utilize it instead of testing the nested property in an earlier condition.
Also, because DeviceCount
is not a component, it shouldn't start with a capital letter. It looks like it may be used as a custom hook, so consider renaming it to useDeviceCount
.
export const useDeviceCount = ({ home }: IDeviceCount) => {
let sensorCount = 0;
let hubcount = 0;
home?.rooms?.forEach((room) => {
room?.nodes?.forEach((node) => {
if (["11", "12", "13", "14", "15"].includes(node?.type)) {
sensorCount ;
} else {
hubcount ;
}
});
});
return { sensorCount, hubcount };
};
(Check the IDeviceCount
type. Does it really have so many possibly undefined nested properties? It seems strange - you may be able to get rid of a few of those optional chains.)
Another approach would be to map each room and node to a flat array of types first, then iterate over that.
export const useDeviceCount = ({ home }: IDeviceCount) => {
let sensorCount = 0;
let hubcount = 0;
const nodeTypes = home?.rooms?.flatMap(
room => room?.nodes?.map(node => node?.type)
);
for (const type of nodeTypes) {
if (["11", "12", "13", "14", "15"].includes(type)) {
sensorCount ;
} else {
hubcount ;
}
}
return { sensorCount, hubcount };
};
CodePudding user response:
You could certainly optimise this somewhat.
For example, you could flatten the arrays and filter the result on a Set
(for O(1) lookups)
const typeFilter = new Set(["11", "12", "13", "14", "15"]);
const nodeTypes =
home.rooms?.flatMap((room) => room.nodes?.map(({ type }) => type) ?? []) ??
[];
const sensorCount = nodeTypes.filter((type) => typeFilter.has(type)).length;
const hubcount = nodeTypes.length - sensorCount;
CodePudding user response:
Not sure how would you like to improve it, I would use two reduce to chain this function like this.
export const DeviceCount = ({ home }: IDeviceCount) => {
return home?.rooms
?.reduce(
(previousValue, home) =>
home?.nodes ? [...previousValue, ...home?.nodes] : previousValue,
[]
)
.reduce(
(previousValue, { hubcount, sensorCount }) =>
['11', '12', '13', '14', '15'].includes(node?.type)
? { hubcount, sensorCount: sensorCount 1 }
: { hubcount: hubcount 1, sensorCount },
{ hubcount: 0, sensorCount: 0 }
);
};
CodePudding user response:
You could create a set of all the sensor node types. Then, loop through the arrays and increment the appropriate variables conditionally. If you are using ?.
, you don't need to add the &&
checks. If the property being checked is nullish, the ?.
will immediately return the nullish value and won't check access the further properties in the .
chain
export const DeviceCount = ({ home }: IDeviceCount) => {
let sensorCount = 0,
hubcount = 0,
sensorTypes = new Set(["11", "12", "13", "14", "15"]);
home?.rooms?.forEach(room =>
room?.nodes?.forEach(node =>
sensorTypes.has(node.type)
? sensorCount
: hubcount ;
)
);
return { sensorCount, hubcount };
};