How to search an array?


#1

I have an array of data. The position I need has been anywhere from position 6 to 11 so far.
It always starts with an "A".
It is METAR data. I have converted the string to an array and everything works fine as long as I set the position of my array correctly.
I need it to know how to search the array for the data I want.



#2

Bit hard to help when you don't say what you are looking for... but it's standard javascript so iterating over an array then comparing an element within is well known to google.


#3

Sorry, I'm not very familiar with javascript and am still learning.

The data I am looking for is the "A2970".
But it the number changes and its position changes, but it always starts with an "A".

I will Google iterating the array.


#4

I guess you will end up using a REGEX expression to parse your METAR string.

One way to use regex in node-RED (among others) is inside a change node, using a jsonata expression.

The bottom line is that you may need to learn regex and jsonata.

Here is a link to the jsonata expression that will find a substring using regex:

https://docs.jsonata.org/string-functions.html

Here is how your node-RED flow will looks like:

[{"id":"48ddfa0a.46dd14","type":"tab","label":"Flow 9","disabled":false,"info":""},{"id":"1a72ae34.a7b9c2","type":"inject","z":"48ddfa0a.46dd14","name":"","topic":"","payload":"METAR KABC 121755Z AUTO 21016G24KT 180V240 1SM R11/P6000FT -RA BR BKN015 OVC025 06/04 A2990 RMK AO2 PK WND 20032/25 WSHFT 1715 VIS 3/4V1 1/2 VIS 3/4 RWY11 RAB07 CIG 013V017 CIG 017 RWY11 PRESFR SLP125 P0003 60009 T00640036 10066 21012 58033 TSNO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":280,"wires":[["ffe1aa8d.390ad8"]]},{"id":"bc18901.a1abc7","type":"debug","z":"48ddfa0a.46dd14","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"result","x":570,"y":280,"wires":[]},{"id":"ffe1aa8d.390ad8","type":"change","z":"48ddfa0a.46dd14","name":"","rules":[{"t":"set","p":"result","pt":"msg","to":"$match(payload,/A\\d{4}/)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":280,"wires":[["bc18901.a1abc7"]]}]

Explaining:

The change node is configured like below:

r-01

It will search the string stored in msg.payload for a substring that starts with A and is followed by four digits. The result of this search will be stored in msg.result and will indicate what is the substring and where it starts.

r-02


#5

I think @Andrei's code assumes you first feed the array into a split node to split it into a sequence of individual messages.


#6

no - it is searching the original string for A followed by 4 digits.


#7

Oh yes, I had not noticed that it says to run it on the original string.


#8

Updated and working. Thank you for all the help.
Now to move it over to a RPiZeroW.


#9

$match(payload,/A\d{4}/)

So I wondered about finding Z and the 6 numbers before it.
I played around with it and read the link provided (I was lost with it) and another I found by a google search of $match(payload,/A\d{4}/).

After reading several times I finally had an aha moment and tried this.
$match(payload,/\d{6}Z/)
It worked. and much cleaner than my slicing.

Thanks for pointing me in the correct direction.


#10

If I may suggest some minor enhancements to the JSONata expression...

You can isolate just the numeric portion of the data to be returned by putting them in a "capture group" -- that's the part of the regex inside the parens: / A(\d{4}) /

I would use the spaces around that section of the METR string to avoid finding the same pattern inside another longer string. Then, you can ask JSONata to return just the captured "string" of 4 digits, and convert it to a number, using this expression:

payload.$match(/ A(\d{4}) /).groups[0].$number()

BTW, is it possible that the numeric value could be not exactly 4 digits? if so, just change the regex to specify a range of lengths (e.g. 3-5 digits), using the syntax / A(\d{3,5}) /


#11

Incidentally, if you just want to "clip" that portion out of the METAR string (ignoring the rest), you can use the "Change" option as well:

In this example, the "Search for" string includes wildcards (.*) that match the beginning and end of the string -- then the "Replace with" string references those captured digits by position (the $1 is the first capture group), effectively replacing the whole incoming payload with just those four numbers (as datatype "string"). FWIW...


#12

Thank you. That is good information for future projects. In this case the number length is always the same. It just sometimes has other data in front of it. So it appears to move around in the string.

I also like your improved version. As all I am needing is the numeric value.

In this case I also have to do some math so just change wont work for me.
At least with my current knowledge of the programming language.


#13

You may find the Range node useful, if you need to scale and/or offset the value.