Does anybody know how .filter exactly works?
Let’s assume we have 100 items in a group gAllLights and we want to swich them all off. There are 2 ways of achieving this (if we want to avoid sending a command OFF to an item which is already OFF):
Method 1 (.filter):
items.getItem("gAllLights").members
.filter(i => i.numericState == 0)
.forEach( i => i.sendCommand("OFF"));
Method 2 (if-clause):
var i_list = items.getItem('gAlLights').members;
for (var i_index in i_list) {
i = i_list[i_index];
if (i.numericState == 0) {
i.sendCommand('OFF');
I do not know exactly how .filter works but I assume that method 1 is faster. What do you think?
Even if the question is probably more of an academic nature , I like to understand the principles anyway.
The reason for asking this is because there does not seem to be a .filter expression available yet in blockly, so that I already realized my script by using method 2.
The filter method runs passes each element in an array to the defined function and if the result of that function is true then that element is included in the resultant array.
With enough elements, the second one is probably slightly faster because you only loop though all the elements once, test each element, and then send the command immediately upon getting the results of the test. In the first version, you loop though all the elements once to test whether to include them in a filtered array and then loop through the filtered array to send the commands, so you are iterating twice on any elements that pass through the filter.
I doubt there’s much of a performance difference between your two examples, unless you have thousands of lights, but I think that’s probably the (ever so slightly) more efficient version.
Just for completeness, sake, I find that the first command is much more readable. If you were to be using direct JS instead of Blockly, you can render the second command in the same format as the first:
items.getItem("gAllLights").members
.forEach( i => if (i.numericState == 0) { i.sendCommand("OFF") } );
But, even better, the helper library has a very nice shortcut for this:
items.getItem("gAllLights").members
.forEach( i => i.sendCommandIfDifferent("OFF") );
which gets you the efficient single iteration, only sending the command to items that need it, and maximum readability.
One last thing: If your items are Switch type, then i.numericState == 0 will not work. Only items with states that can be directly parsed to numbers will return a value with numericState. So, I assume that all the lights you are testing are Dimmer type.