# Is this a job for an array?

**URL:** https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537
**Category:** General
**Created:** [5 July 2020 08:35 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537 "2020-07-05T08:35:20Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![impvan](https://avatars.discourse-cdn.com/v4/letter/i/8797f3/32.png) [@impvan](https://discourse.nodered.org/u/impvan)
#### Post date: [5 July 2020 08:35 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/1 "2020-07-05T08:35:20Z")

</div>

I have a large number of sensors, which return ID:value pairs like this-

```auto
DS18B20-1: object
    Id: "030197946C6B"
    Temperature: 21.6

```

I want to change each ID into a 'friendly name', and also to apply a offset against each ID to compensate for each sensor's innacuracy.  
I'm thinking of a table, with |ID|FriendlyName|Offset| rows. I need to access the table from any flow.

**Question: is an array the correct approach for this "look-up table"?**

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [5 July 2020 08:49 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/2 "2020-07-05T08:49:04Z")

</div>

You could create a lookup object and store it in flow or global context.

E.g...

Inject \> change node

The change node would set flow.offsets to something like...

```auto
{
"030197946C6B":-5.88,
"030197946C7C":12.63
}

```

Then whenever you need to grab the offset use a function node...

```auto
var id = msg.payload.Id;//or wherever you get the id from
var offsets = flow.get("offsets") || {};// get the lookup object
var offset = offsets[id];//perform lookup to get offset

```

Notes...  
I have not added any defaults or error checking  
You would be wise to store not just an offset number in the lookup but an actual object for future extensibility (e.g don't just store a number, store an object with the offset, calibration date, who calibrated, a friendly name, other relevant data)

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [5 July 2020 10:06 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/3 "2020-07-05T10:06:39Z")

</div>

> [@impvan](#):
>
> I want to change each ID into a 'friendly name'

As Steve say's, in Javascript this would be an Object.

```auto
{
    "030197946C6B": "My nice friendly name",
    ...
}

```

I go further and have various "meta-data" in a lookup table:

```auto
{
    "030197946C6B": {
        "name": "Friendly Name",
        "location": "Living Room",
        "sensors": "THL", // T=Temperature, H=Humidity, L=Light - this could be an array instead
        ...
    },
    ...
}

```

Using an array would be a pain since you would have to walk the array (do a search through it) every time you wanted to look up the data for the sensor. Nice thing about using newer versions of JavaScript is that you can use an Object as an array simply by doing `Object.values(obj)`. you can also get all of the keys as an array with `Object.keys(obj)`. Both can be useful if you do need to walk through a complete object (for example to return all of the object to ui\_table or the equivalent in uibuilder).

---

<div class="post-metadata">

### Author: ![impvan](https://avatars.discourse-cdn.com/v4/letter/i/8797f3/32.png) [@impvan](https://discourse.nodered.org/u/impvan)
#### Post date: [5 July 2020 19:26 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/4 "2020-07-05T19:26:00Z")

</div>

I can certainly see the usefulness in the 'meta-data' concept.

What's the wrapper for this look-up table? Inside a Function node?

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [5 July 2020 19:33 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/5 "2020-07-05T19:33:50Z")

</div>

> [@impvan](#):
>
> What's the wrapper for this look-up table? Inside a Function node?

Do you mean where is the lookup object stored or generated?

As i wrote in my first post, you can use an inject and change node to generate the JS object & store it in flow or global. Then a function node (using `flow.get`) to retrieve it

e.g....

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/8/08ffe59ab74a7f1734930826e7d0d6bc4a4e2183.png)

```auto
[{"id":"c1159f62.90212","type":"comment","z":"eea1fe59.ca838","name":"Initialise lookup object & store it in flow context","info":"","x":950,"y":80,"wires":[]},{"id":"e55f078d.4590e8","type":"inject","z":"eea1fe59.ca838","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":840,"y":120,"wires":[["b04c7d77.b4b64"]]},{"id":"b04c7d77.b4b64","type":"change","z":"eea1fe59.ca838","name":"","rules":[{"t":"set","p":"sensors","pt":"flow","to":"{\"030197946C6B\":{\"name\":\"Sensor 1\",\"location\":\"greenhouse\",\"calibationOffset\":-5.12},\"030197946C7A\":{\"name\":\"Sensor 2\",\"location\":\"outhouse\",\"calibationOffset\":1.74}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1040,"y":120,"wires":[[]]},{"id":"fdf6e51b.e8f788","type":"inject","z":"eea1fe59.ca838","name":"","topic":"","payload":"030197946C6B","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":820,"y":220,"wires":[["f1dcf04.e4b191"]]},{"id":"7256044a.770ebc","type":"inject","z":"eea1fe59.ca838","name":"","topic":"","payload":"030197946C7A","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":820,"y":260,"wires":[["f1dcf04.e4b191"]]},{"id":"602a40cf.ade86","type":"debug","z":"eea1fe59.ca838","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1230,"y":220,"wires":[]},{"id":"1d7ec3aa.a4eeac","type":"comment","z":"eea1fe59.ca838","name":"Get lookup object from flow context","info":"","x":880,"y":180,"wires":[]},{"id":"f1dcf04.e4b191","type":"function","z":"eea1fe59.ca838","name":"get sensor details","func":"var id = msg.payload;//or wherever you get the id from\nvar sensors = flow.get(\"sensors\") || {};// get the lookup object\nmsg.payload = sensors[id];//perform lookup to get offset\nmsg.payload.id = id;\nreturn msg;","outputs":1,"noerr":0,"x":1050,"y":220,"wires":[["602a40cf.ade86"]]}]

```

---

<div class="post-metadata">

### Author: ![impvan](https://avatars.discourse-cdn.com/v4/letter/i/8797f3/32.png) [@impvan](https://discourse.nodered.org/u/impvan)
#### Post date: [5 July 2020 19:40 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/6 "2020-07-05T19:40:00Z")

</div>

Ah, thanks for that example ~ I can see the 'table' buried in the Change node...

Even more learning required methinks!

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [5 July 2020 19:42 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/7 "2020-07-05T19:42:49Z")

</div>

The "table" is a text representation of a JavaScript object (or JSON - JavaScript Object Notation)

Something you will become aware of as you get more familiar with this environment.

So this example creates a JS "lookup" object and stores it in `flow` memory

Then the function node GETS the object out of flow context and then performs a lookup (I commented up the code to help you)

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [5 July 2020 19:46 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/8 "2020-07-05T19:46:06Z")

</div>

> [@Steve-Mcl](#):
>
> As i wrote in my first post, you can use an inject and change node to generate the JS object & store it in flow or global

That's how I generally do it but I use a persistent global variable so I no longer have to run it every time Node-RED restarts, only when it changes. You could, of course, also add a simple web interface to update it rather than having to use the Editor UI each time - though unless you have multiple people doing editing of flows or you want your family or non-NR using colleagues to edit it, there is little benefit. The inject node now has a nice JSON editor built in which makes it easy.

Over time you can then integrate other ways to change the meta-data if you wanted to. With Node-RED, you don't have to do everything at once.

Here is a single inject node with the data from my example above:

```auto
[{"id":"4578c040.57087","type":"inject","z":"a851b997.a01c18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"030197946C6B\":{\"name\":\"Friendly Name\",\"location\":\"Living Room\",\"sensors\":\"THL\"}}","payloadType":"json","x":300,"y":300,"wires":[[]]}]

```

And here are the 2 simple flows - 1 to set the metadata and 1 that simulates incoming data from your sensor and combines with the metadata:

```auto
[{"id":"4578c040.57087","type":"inject","z":"a851b997.a01c18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"030197946C6B\":{\"name\":\"Friendly Name\",\"location\":\"Living Room\",\"sensors\":\"THL\"}}","payloadType":"json","x":310,"y":300,"wires":[["babc5eb4.40533"]]},{"id":"60a5f2f4.37284c","type":"function","z":"a851b997.a01c18","name":"","func":"/*jshint asi:true*/\n\nconst id = msg.payload.Id\n\nconst meta = flow.get('meta')\n\nif ( meta[id] ) {\n msg.payload.name = meta[id].name\n // ...\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":460,"y":380,"wires":[["d32e9eba.f4cc1"]]},{"id":"1b7786b2.601c89","type":"inject","z":"a851b997.a01c18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"Id\":\"030197946C6B\",\"Temperature\":21.6}","payloadType":"json","x":310,"y":380,"wires":[["60a5f2f4.37284c","95dfe296.3bd2b"]]},{"id":"babc5eb4.40533","type":"change","z":"a851b997.a01c18","name":"","rules":[{"t":"set","p":"meta","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":300,"wires":[[]]},{"id":"d32e9eba.f4cc1","type":"debug","z":"a851b997.a01c18","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":380,"wires":[]}]

```

You could do it with JSONata as well but for me, JS is usually quicker and easier for most things.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [3 September 2020 19:46 UTC](https://discourse.nodered.org/t/is-this-a-job-for-an-array/29537/9 "2020-09-03T19:46:08Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
