# How to optimize sending associativ array (filter payload)

**URL:** <https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246>\
**Category:** General\
**Created:** [27 November 2018 21:23 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246 "2018-11-27T21:23:25Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![dark\_vidor](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dark_vidor/32/4066_2.png) [@dark\_vidor](https://discourse.nodered.org/u/dark_vidor)\
**Post date:** [27 November 2018 21:23 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/1 "2018-11-27T21:23:25Z")

</div>

Hello,

I have this payload (for exemple) : `payload : [[0,"300",0,0,0,0,0],[0,0,0,0,0,0,0]]`  
I would like to send : `payload : {"0":{"1":300}}`

Also if my payload will be : `payload : [[0,"300",0,"500",0,0,0],[0,0,"200",0,0,0,0]]`  
My message will have to be `payload : {"0":[{"1":300}, {"3":500}], "1":{"2":200}}` or `{"0":[[1,3],[300,500]], "1":[[2],[200]]}` (second is more optimized ?)

Do you know how make this or with an other way using native fonction ?  
Thank for your feedback

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [27 November 2018 23:22 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/2 "2018-11-27T23:22:44Z")

</div>

Well, I don't know of any "native" function, but I generally like to use a JSONata expression to morph one structure into another -- I plugged your data into the jsonata exerciser site and developed this expression:

```auto
payload~>$map(function($arr, $ind) {
	(
    	$tmp := $map($arr, function($v, $i) {
        	{"index": $i, "value": $number($v)}
        });
        {
        	$string($ind): [
	            [$tmp[value > 0].index],
    	        [$tmp[value > 0].value]
            ]
        }
    )
})~>$merge()

```

The output seems to match your second (optimized) output style... if you put this into a `change` node,  
just make sure to select the `J:` pulldown, click the three dots `...` to open the edit panel, and paste the expression. There is even an expression "tester" tab where you can put your actual payload data and see how the output changes as you modify the expression:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/c/c2827863f2ddb3e200ee8074cd3f10799ff05c27.png)

Or you can simply import this node...

```auto
[{"id":"e496cac4.80f788","type":"change","z":"d59690cd.1ee8c","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload~>$map(function($arr, $ind) {\t\t(\t \t$tmp := $map($arr, function($v, $i) {\t \t{\"index\": $i, \"value\": $number($v)}\t });\t {\t \t$string($ind): [\t\t [$tmp[value > 0].index],\t \t [$tmp[value > 0].value]\t ]\t }\t )\t})~>$merge()\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1560,"y":320,"wires":[[]]}]

```

---

<div class="post-metadata">

**Author:** ![dark\_vidor](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dark_vidor/32/4066_2.png) [@dark\_vidor](https://discourse.nodered.org/u/dark_vidor)\
**Post date:** [29 November 2018 08:32 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/3 "2018-11-29T08:32:27Z")

</div>

Hello @shrickus,  
Thank you for your reply.

It work, but for example :  
[[0,300,0,500,0,0,0],[0,0,0,0,0,0,0]] ==\> {"0":[[1,3],[300,500]],"1":[[],[]]}

Is it possible to remove the "1" attribute ?

Is it possible to do a generic function for all array with 2 / 3 sub level ?

I didn't know this programming method ...

---

<div class="post-metadata">

**Author:** ![ukmoose](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ukmoose/32/13_2.png) [@ukmoose](https://discourse.nodered.org/u/ukmoose)\
**Post date:** [29 November 2018 09:41 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/4 "2018-11-29T09:41:28Z")

</div>

Theres a jsonata exerciser at [http://try.jsonata.org](http://try.jsonata.org)  
Where you can import your input data and have a play

---

<div class="post-metadata">

**Author:** ![dark\_vidor](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dark_vidor/32/4066_2.png) [@dark\_vidor](https://discourse.nodered.org/u/dark_vidor)\
**Post date:** [29 November 2018 11:57 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/5 "2018-11-29T11:57:43Z")

</div>

I alredy find & try... but i don't know jsonata ☹

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [29 November 2018 16:38 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/6 "2018-11-29T16:38:55Z")

</div>

> [@dark\_vidor](#):
>
> but i don't know jsonata

never a better time than now to start learning 😁  
Try google with 'jsonata tutorial'

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [29 November 2018 22:21 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/7 "2018-11-29T22:21:30Z")

</div>

> [@dark\_vidor](#):
>
> Is it possible to remove the "1" attribute ?
> 
> Is it possible to do a generic function for all array with 2 / 3 sub level ?

It's pretty easy, once you understand the syntax -- so "no" it's probably not possible to figure out for the casual observer... here's how I would solve it:

```auto
payload~>$map(
    function($arr, $ind) {
        (
            $tmp := $map(
                $arr,
                function($v, $i) {
                    $number($v) ?
                    {
                        "index": $i,
                        "value": $number($v)
                    }
                }
            );
            {
                $string($ind): $tmp[value > 0] ? [
                    [$tmp[value > 0].index],
                    [$tmp[value > 0].value]
                ]
            }
        )
    }
)~>$merge()

```

Notice the addition of the filter `$tmp[value > 0] ?` which only creates the output array IF there are any values greater than 0.

---

<div class="post-metadata">

**Author:** ![dark\_vidor](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dark_vidor/32/4066_2.png) [@dark\_vidor](https://discourse.nodered.org/u/dark_vidor)\
**Post date:** [30 November 2018 09:58 UTC](https://discourse.nodered.org/t/how-to-optimize-sending-associativ-array-filter-payload/5246/8 "2018-11-30T09:58:06Z")

</div>

Thank you @shrickus,  
This syntax is not usual for me ...

I try this

> `payload~\>$map( function($arr, $ind) {  
> (  
> $tmp := $map( $arr, function($v, $i){ $number($v) ? { "index": $i, "value": $number($v) } });
> 
> ```
> { $string($ind): $tmp[value > 0] ? $each( $tmp[value > 0], function($v, $i){ {$string($i):$v} }) }
> )
> 
> ```
> 
> })~\>$merge()`

To do that : `payload : {"0":[{"1":300}, {"3":500}], "1":{"2":200}}` but that don't find matches ☹

In fact, after i would like to compare 2 payload to make a filter .. 🤯
