How to loop an array?

Hi,

can you please help me to find out how to go through an array and perform an action on every element in this array ?

Something like that:

MQTT_Array = ["sonoff/sonoff082/STATUS8","sonoff/sonoff084/SENSOR","sonoff/sonoff085/STATUS8","sonoff/sonoff086/STATUS8","sonoff/sonoff087/STATUS8","sonoff/sonoff089/SENSOR","sonoff/sonoff091/STATUS8","sonoff/sonoff092/SENSOR"]


for ("every element in MQTT_Array")
{
    var value = global.get('array_element.Value'); 
    if (value > 5) 
    {
        return msg;
    }
    else
    {
        return null;
    }
}

You can use every() on an array to invoke a function for every element. Alternatively if you put the array in msg.payload and pass it to a Split node you can split the array into a stream of messages which you can then pass to nodes to perform whatever action is desired.

Personally, I am using the array loop node from (node-red-contrib-loop-processing). I find it very convenient (and simple) for a beginner like me!
GV

for (var element of array) {
node.warn(element)
}

or

for (var index in array) {
 node.warn(array[index])
}

Better (order consisted)

array.forEach(function (value,index) {
});
1 Like

The forEach syntax is the only one that should be used in this instance. for of has its place, but is much slower than forEach. for in on an array should never be used.

1 Like

Interesting! Have you run performance tests on different access methods (and if so, can you describe how)?

Being a long-time C/C++ coder, I tend to use e.g.

for (idx=0; idx<array.length; idxx++)

which I'd assumed would be the fastest, but I'd be interested to hear if it actually was.

There's a bunch of tests on JSPerf. Check them out for the results. Your browser will impact the results, but it's a good measure nonetheless.

1 Like

Thanks - I'll give it a go.

Remember that it is nodejs that is executing the code not the browser, so strictly you would need to run the tests in node.js.

1 Like

If you set the tests up properly, the difference is negligible. This makes sense since both environments are using the same engine, if you're using Chrome.

1 Like

to be honest, I do not really get the "function (value,index)" part of this solution ... what can I do with that ?

MQTT_Array = ["sonoff/sonoff082/STATUS8","sonoff/sonoff084/SENSOR","sonoff/sonoff085/STATUS8","sonoff/sonoff086/STATUS8","sonoff/sonoff087/STATUS8","sonoff/sonoff089/SENSOR","sonoff/sonoff091/STATUS8","sonoff/sonoff092/SENSOR"]

MQTT_Array.forEach(function (value,index) {
});

for ("every element in MQTT_Array")
{
    var value = global.get('array_element.Value'); 
    if (value > 5) 
    {
        return msg;
    }
    else
    {
        return null;
    }
}
MQTT_Array.forEach(function (value,index) {
   if (value > 5) 
    {
        return msg;
    }
    else
    {
        return null;
    }
});

However I am not sure that is actually what you want to do. What exactly are you trying to achieve?

What should be used for nested loops. Many editors complain not to define a function inside an forEach function. Is the warning related to the stack or performance?

I probably would not do that, mostly because keeping track of the brackets and parentheses becomes a nightmare. The cleaner way to do it is to take the inline function definition out. So you end up with something like

MQTT_Array.forEach(doIt);

function doit(value,index) {
   if (value > 5) 
    {
        return msg;
    }
    else
    {
        return null;
    }
}

And do the same thing again if there is a nested forEach() required.

function doStuff(/*params that make sense */) {

}

arr.map(val => {
   returm doStuff(val);
});

Alternatively, you can write these a bit more terse.

function convertToObjects (value) {
    return mapValToProps(value);
}

function mapValToProps(value) {
    return {
        lightBulb: value.ah_Ha;
    };
}

arr.map(convertToObjects);

Most of the examples you see have inlined functions, but that doesn't mean you can define the function elsewhere and use it as a callback. :wink: When I'm debugging, sometimes I'll even do this arr.forEach(console.log);

Thank you for sharing another approach. Perhaps it is important to point out that there is a different usecase for forEach and map

As I read the docs the map method is useful if you need each result of each iteration as map returns a new array containing the results
of each iteration

The map() method creates a new array with the results of calling a function for every array element.

The map() method calls the provided function once for each element in an array, in order.

In your first example I would use forEach() instead of map() because the result will be unused.

BTW: console.log by itself does nice colorful formatting of arrays and objects by itself.

There is a rundown of many possible debug log options including console.log()

for in loops over enumerable property names of an object.

for of (new in ES6) does use an object-specific iterator and loops over the values generated by that.

"forEach...in" iterates a specified variable over all values of the specified object's properties.