How to do a simple sum of two msgs which are arrays

#1

Hello,

I'm still stuck with this topic where I want to sum up two arrays from different msgs.
flow
debug

I want to create a new array in the debug mode from those 2 msgs: array a + array b = array c; [1, 2, 3, 4] + [4, 3, 2, 1] = [5, 5, 5, 5]

I tried the join node, but I didnt figure out how to deal with 2 different msgs.
Could someone help me? Thanks a lot :slight_smile:

#2

Hi @elchmo

It will depend on how you configured the Join node and how you expect those two separate messages to arrive.

a Join node configured to 'manual' mode, to combine each msg.payload to create an Array, and set to send after 2 message parts are received, will wait for each pair of messages and combine them into one with a payload of:

{ payload: [ [1,2,3,4], [4,3,2,1] ] }

Once they are in a single message, a Function node can sum the arrays:

var result = [];
msg.payload[0].forEach(function(v,i) {
   result.push(v+msg.payload[1][i]); 
});
msg.payload = result;
return msg;

There may be a way to do that sum using a Change node with a JSONata expression... but I'll leave that as a exercise for others.

This approach assumes the messages always arrive as pairs - you always get one 'array a' and one 'array b'. If you get two instances of 'array a' before an 'array b' arrives, you'll get the sum of the two 'array a's.

#3

So that means I can't get an array c as sum out of a and b? I mean this is my current code and i just don't know what to do :frowning: [{"id":"90f4c870.6e16d8","type":"inject","z":"69fd5631.e3f32c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":540,"wires":[["50e12739.187368","2d40c77a.d6e858"]]},{"id":"baa5cb9.3666a38","type":"debug","z":"69fd5631.e3f32c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":750,"y":540,"wires":[]},{"id":"50e12739.187368","type":"function","z":"69fd5631.e3f32c","name":"array a","func":"var a = [1, 2, 3, 4];\nmsg.payload = a;\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":520,"wires":[["b7d9e3e8.38cd1"]]},{"id":"2d40c77a.d6e858","type":"function","z":"69fd5631.e3f32c","name":"array b","func":"var b = [4, 3, 2, 1];\nmsg.payload = b;\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":560,"wires":[["b7d9e3e8.38cd1"]]},{"id":"b7d9e3e8.38cd1","type":"join","z":"69fd5631.e3f32c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":570,"y":540,"wires":[["baa5cb9.3666a38"]]}]

#4

I described how to do it. Join the arrays and use a Function node to sum them. Is that not what you want?

[{"id":"8c61ff89.907a1","type":"inject","z":"24d928f3.3c58f8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":340,"wires":[["b0a5b776.cc0ec8","1d512dac.dcf892"]]},{"id":"b0a5b776.cc0ec8","type":"change","z":"24d928f3.3c58f8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[1,2,3,4]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":320,"wires":[["4f2d89ed.bacd88"]]},{"id":"1d512dac.dcf892","type":"change","z":"24d928f3.3c58f8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[5,6,7,8]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":360,"wires":[["4f2d89ed.bacd88"]]},{"id":"b4284113.82a9b","type":"function","z":"24d928f3.3c58f8","name":"","func":"\nvar result = [];\nmsg.payload[0].forEach(function(v,i) {\n   result.push(v+msg.payload[1][i]); \n});\nmsg.payload = result;\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":340,"wires":[["fad8c15.2e5684"]]},{"id":"fad8c15.2e5684","type":"debug","z":"24d928f3.3c58f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":340,"wires":[]},{"id":"4f2d89ed.bacd88","type":"join","z":"24d928f3.3c58f8","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":550,"y":340,"wires":[["b4284113.82a9b"]]}]

(Please read this post about sharing flows on the forum: How to share code or flow json)

1 Like
#5

Thanks man :smiley:

but now I have another problem... does that bother you?

I have this code where i want to sum up the more complicated arrays.

[{"id":"7f7e006e.6b431","type":"function","z":"69fd5631.e3f32c","name":"Calculate mean","func":"// Width and height of heating fields in pixels\n// dependant on the distance between camera and object\nconst FIELD_WIDTH = 2;\nconst FIELD_HEIGHT = 2;\n\n//WIDTH Resolution of Image\n//unused\nconst RES_WIDTH = 12;\n\n// # of heating fields to calculate\nconst FIELDS_HORIZONTAL = 4;\nconst FIELDS_VERTICAL = 6;\n\n// start at left upper corner\nconst HEATING_FIELD_START_HORIZONTAL = 0\n\n// start at left upper corner\nconst HEATING_FIELD_START_VERTICAL = 0;\n\n\ninputArray = new Array(msg.payload.length);\n\n//the payload is an array of objects, but an array of arrays is needed. \n//this loop creates an array of arrays for better handling\nfor(var n = 0; n < inputArray.length; n++){\n inputArray[n] = Object.values(msg.payload[n]);\n}\n\n\n//creating an empty outputArray with the set number of fields\nvar outputArray2 = new Array(FIELDS_VERTICAL);\n\nfor(var k = 0; k < outputArray2.length; k++){\n outputArray2[k] = new Array(FIELDS_HORIZONTAL);\n for(var l = 0; l < outputArray2[k].length; l++){\n outputArray2[k][l] = 0;\n }\n}\n\n\n\n//loop through the fields\n//runs through first row, then second, then third...\nfor(var v = 0; v < FIELDS_VERTICAL; v++){\n for(var h = 0; h < FIELDS_HORIZONTAL; h++){\n \n //calculate the median of each field\n var tmp = 0;\n \n for(var y = HEATING_FIELD_START_VERTICAL + v * FIELD_HEIGHT; y < HEATING_FIELD_START_VERTICAL + v * FIELD_HEIGHT + FIELD_HEIGHT; y++){\n for(var x = HEATING_FIELD_START_HORIZONTAL + h * FIELD_WIDTH; x < HEATING_FIELD_START_HORIZONTAL + h * FIELD_WIDTH + FIELD_WIDTH; x++){\n tmp += parseInt(inputArray[y][x]);\n } \n }\n //round to 2 decimals\n tmp = tmp / (FIELD_WIDTH * FIELD_HEIGHT);\n tmp = Math.round(tmp * 100) / 100;\n outputArray2[v][h] = tmp;\n \n }\n}\n\nflow.set(\"outputArray2\", msg.payload);\nmsg.payload = outputArray2;\n\nreturn msg;","outputs":1,"noerr":0,"x":740,"y":120,"wires":[["d48e8e79.23e11"]]},{"id":"d48e8e79.23e11","type":"debug","z":"69fd5631.e3f32c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":930,"y":140,"wires":[]},{"id":"ca9abe43.08e73","type":"inject","z":"69fd5631.e3f32c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":140,"wires":[["fa7d0a6b.57f7c8","6da5596b.f5e328"]]},{"id":"fa7d0a6b.57f7c8","type":"file in","z":"69fd5631.e3f32c","name":"soll wert","filename":"\\\\bsh.corp.bshg.com\\fredirect\\DE\\GIN\\HoangT\\Desktop\\soll wert\\Mappe1.csv","format":"utf8","chunk":false,"sendError":false,"x":440,"y":120,"wires":[["d926ceff.7e151"]]},{"id":"d926ceff.7e151","type":"csv","z":"69fd5631.e3f32c","name":"Read csv","sep":";","hdrin":"","hdrout":"","multi":"mult","ret":"\\n","temp":"","skip":"0","x":580,"y":120,"wires":[["7f7e006e.6b431"]]},{"id":"6da5596b.f5e328","type":"file in","z":"69fd5631.e3f32c","name":"ist wert","filename":"\\\\bsh.corp.bshg.com\\fredirect\\DE\\GIN\\HoangT\\Desktop\\testcsv\\Mappe1.csv","format":"utf8","chunk":false,"sendError":false,"x":440,"y":160,"wires":[["ccfd7c5f.71fcc"]]},{"id":"ccfd7c5f.71fcc","type":"csv","z":"69fd5631.e3f32c","name":"Read csv","sep":";","hdrin":"","hdrout":"","multi":"mult","ret":"\\n","temp":"","skip":"0","x":580,"y":160,"wires":[["f2a18d8d.b226e"]]},{"id":"f2a18d8d.b226e","type":"function","z":"69fd5631.e3f32c","name":"Calculate mean","func":"// Width and height of heating fields in pixels\n// dependant on the distance between camera and object\nconst FIELD_WIDTH = 2;\nconst FIELD_HEIGHT = 2;\n\n//WIDTH Resolution of Image\n//unused\nconst RES_WIDTH = 12;\n\n// # of heating fields to calculate\nconst FIELDS_HORIZONTAL = 4;\nconst FIELDS_VERTICAL = 6;\n\n// start at left upper corner\nconst HEATING_FIELD_START_HORIZONTAL = 0\n\n// start at left upper corner\nconst HEATING_FIELD_START_VERTICAL = 0;\n\n\ninputArray = new Array(msg.payload.length);\n\n//the payload is an array of objects, but an array of arrays is needed. \n//this loop creates an array of arrays for better handling\nfor(var n = 0; n < inputArray.length; n++){\n inputArray[n] = Object.values(msg.payload[n]);\n}\n\n\n//creating an empty outputArray with the set number of fields\nvar outputArray2 = new Array(FIELDS_VERTICAL);\n\nfor(var k = 0; k < outputArray2.length; k++){\n outputArray2[k] = new Array(FIELDS_HORIZONTAL);\n for(var l = 0; l < outputArray2[k].length; l++){\n outputArray2[k][l] = 0;\n }\n}\n\n\n\n//loop through the fields\n//runs through first row, then second, then third...\nfor(var v = 0; v < FIELDS_VERTICAL; v++){\n for(var h = 0; h < FIELDS_HORIZONTAL; h++){\n \n //calculate the median of each field\n var tmp = 0;\n \n for(var y = HEATING_FIELD_START_VERTICAL + v * FIELD_HEIGHT; y < HEATING_FIELD_START_VERTICAL + v * FIELD_HEIGHT + FIELD_HEIGHT; y++){\n for(var x = HEATING_FIELD_START_HORIZONTAL + h * FIELD_WIDTH; x < HEATING_FIELD_START_HORIZONTAL + h * FIELD_WIDTH + FIELD_WIDTH; x++){\n tmp += parseInt(inputArray[y][x]);\n } \n }\n //round to 2 decimals\n tmp = tmp / (FIELD_WIDTH * FIELD_HEIGHT);\n tmp = Math.round(tmp * 100) / 100;\n outputArray2[v][h] = tmp;\n \n }\n}\n\nflow.set(\"outputArray2\", msg.payload);\nmsg.payload = outputArray2;\n\nreturn msg;","outputs":1,"noerr":0,"x":740,"y":160,"wires":[["d48e8e79.23e11"]]}]

the csv files look like this (only with different numbers):

Would be nice if you could help me, thank you pretty much :slight_smile:

#6

How to sum elements in an array is fairly basic javascript. If you use your internet search engine of choice you should find many pages that can help you

#7

I searched but I didn't find anything because I have arrays in an array :frowning:

#8

For the record, there are a couple ways I can think of to do this with a JSONata expression -- but if you know you will only have 2 arrays, you can "zip" them together (put matching index elements into their own arrays), and them pass the list to the sum function:

$zip(payload[0],payload[1]).$sum(*)

Another way is the build an object keyed on the array index, and then pull out only the values:

([0..$count(payload)-1].(
	$idx := $;
    {
		$string($idx): $$.payload.*[$idx]~>$sum
	}
)~>$merge()).*