How do I sort an object?

I’m trying to list all my battery powered devices excluding tablets and phones and list all the percentages left.

[{"id":"bb78f07125f8413e","type":"change","z":"ebaa69a9.649708","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"battery_size","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":560,"wires":[["afd464a52b15da53"]]},{"id":"eb6da3b4107fbd1a","type":"inject","z":"ebaa69a9.649708","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":600,"wires":[["2da739aba61004d6","bb78f07125f8413e"]]},{"id":"afd464a52b15da53","type":"ha-get-entities","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","version":0,"rules":[{"property":"attributes.state_class","logic":"is","value":"measurement","valueType":"str"},{"property":"attributes.device_class","logic":"is","value":"battery","valueType":"str"},{"property":"attributes.battery_size","logic":"is","value":".*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":690,"y":560,"wires":[["4604e5a18e2e6b34"]]},{"id":"2da739aba61004d6","type":"change","z":"ebaa69a9.649708","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"battery_voltage","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":620,"wires":[["811736146a2f051a"]]},{"id":"4604e5a18e2e6b34","type":"join","z":"ebaa69a9.649708","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"1","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":850,"y":600,"wires":[["a8cddac6ea3fe7cb"]]},{"id":"811736146a2f051a","type":"ha-get-entities","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","version":0,"rules":[{"property":"attributes.state_class","logic":"is","value":"measurement","valueType":"str"},{"property":"attributes.device_class","logic":"is","value":"battery","valueType":"str"},{"property":"attributes.battery_voltage","logic":"is","value":".*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":690,"y":620,"wires":[["4604e5a18e2e6b34"]]},{"id":"a8cddac6ea3fe7cb","type":"function","z":"ebaa69a9.649708","name":"","func":"var array = {};\nfor (var index in msg.payload.battery_voltage) {\n    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n    array[msg.payload.battery_voltage[index].attributes.friendly_name] = msg.payload.battery_voltage[index].state;\n}\n\nfor (var index in msg.payload.battery_size) {\n    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n    array[msg.payload.battery_size[index].attributes.friendly_name] = msg.payload.battery_size[index].state;\n}\n\n//array.sort((A, B) => B.value - A.value);\nmsg.arr = array;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1000,"y":540,"wires":[["0e0aee1f9fb74388","a25898f22e6e5f71"]]},{"id":"0e0aee1f9fb74388","type":"sort","z":"ebaa69a9.649708","name":"","order":"descending","as_num":false,"target":"arr","targetType":"msg","msgKey":"payload","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":990,"y":680,"wires":[["a25898f22e6e5f71"]]},{"id":"a25898f22e6e5f71","type":"debug","z":"ebaa69a9.649708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1190,"y":640,"wires":[]},{"id":"4bbca37b.1700ec","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

Now I have msg.arr as my devices in a key value pair.

I have tried to use sort in the function node and I have tried sort node but I just can’t get it sorted.
What am I doing wrong here?
I want the lowest battery percentage to be on top

The sort node is used to sort a LIST, not a DICT.

[{"id":"eb6da3b4107fbd1a","type":"inject","z":"6962cd73617689d5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":630,"y":420,"wires":[["a8cddac6ea3fe7cb"]]},{"id":"a8cddac6ea3fe7cb","type":"function","z":"6962cd73617689d5","name":"Create DICT","func":"var array = {['Alice']:1,['Charlie']:4,['Dicte']:2,['Beatrice']:3};\nmsg.arr = array;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":420,"wires":[["0e0aee1f9fb74388","a25898f22e6e5f71"]]},{"id":"0e0aee1f9fb74388","type":"sort","z":"6962cd73617689d5","name":"","order":"descending","as_num":false,"target":"arr","targetType":"msg","msgKey":"payload","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":950,"y":465,"wires":[["a25898f22e6e5f71"]]},{"id":"a25898f22e6e5f71","type":"debug","z":"6962cd73617689d5","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1175,"y":465,"wires":[]},{"id":"57def5b928247706","type":"inject","z":"6962cd73617689d5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":630,"y":510,"wires":[["569632a567ee91c2"]]},{"id":"569632a567ee91c2","type":"function","z":"6962cd73617689d5","name":"Create LIST","func":"var array = ['Alice','Charlie','Dicte','Beatrice'];\nmsg.arr = array;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":510,"wires":[["0e0aee1f9fb74388","a25898f22e6e5f71"]]}]

And a side note:
Avoid using join nodes if you can. The simultaneity issues can be extremely hard to handle correctly.
In this case nothing seems to be preventing from putting the two split flows in serial instead.

Thanks.
But how do I change the function node then?
I don’t understand the syntax in a loop.

I changed your data into a 2 dimensional LIST, which makes the sort work.


[{"id":"0e0aee1f9fb74388","type":"sort","z":"6962cd73617689d5","name":"","order":"descending","as_num":false,"target":"arr","targetType":"msg","msgKey":"payload","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":950,"y":465,"wires":[["a25898f22e6e5f71"]]},{"id":"a25898f22e6e5f71","type":"debug","z":"6962cd73617689d5","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1175,"y":465,"wires":[]},{"id":"57def5b928247706","type":"inject","z":"6962cd73617689d5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":630,"y":510,"wires":[["569632a567ee91c2"]]},{"id":"569632a567ee91c2","type":"function","z":"6962cd73617689d5","name":"Create LIST","func":"var array = [['Alice',1],['Charlie',4],['Dicte',2],['Beatrice',3]];\nmsg.arr = array;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":510,"wires":[["0e0aee1f9fb74388","a25898f22e6e5f71"]]}]

And what part of a loop is confusing?

But you have not changed the dynamic part of my code.
This is not helpful.
What is the syntax to create the list dynamically inside a loop?

So you mean the loop like this?


var array = [];
var i;
for (i = 0; i < msg.payload.battery_voltage.length; i++)
{
    var listelement =[];
    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);
    listelement[0]=array[msg.payload.battery_voltage[index].attributes.friendly_name];
    listelement[1]=msg.payload.battery_voltage[index].state;
    array[i]=listelement;
}
msg.arr = array;
return msg;

Thank you.
But the sorting still is not done.

Did you send it to the sort ode?

Yes.

[{"id":"bb78f07125f8413e","type":"change","z":"ebaa69a9.649708","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"battery_size","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":560,"wires":[["afd464a52b15da53"]]},{"id":"eb6da3b4107fbd1a","type":"inject","z":"ebaa69a9.649708","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":600,"wires":[["2da739aba61004d6","bb78f07125f8413e"]]},{"id":"afd464a52b15da53","type":"ha-get-entities","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","version":0,"rules":[{"property":"attributes.state_class","logic":"is","value":"measurement","valueType":"str"},{"property":"attributes.device_class","logic":"is","value":"battery","valueType":"str"},{"property":"attributes.battery_size","logic":"is","value":".*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":690,"y":560,"wires":[["4604e5a18e2e6b34"]]},{"id":"2da739aba61004d6","type":"change","z":"ebaa69a9.649708","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"battery_voltage","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":620,"wires":[["811736146a2f051a"]]},{"id":"4604e5a18e2e6b34","type":"join","z":"ebaa69a9.649708","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"1","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":850,"y":600,"wires":[["a8cddac6ea3fe7cb"]]},{"id":"811736146a2f051a","type":"ha-get-entities","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","version":0,"rules":[{"property":"attributes.state_class","logic":"is","value":"measurement","valueType":"str"},{"property":"attributes.device_class","logic":"is","value":"battery","valueType":"str"},{"property":"attributes.battery_voltage","logic":"is","value":".*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":690,"y":620,"wires":[["4604e5a18e2e6b34"]]},{"id":"a8cddac6ea3fe7cb","type":"function","z":"ebaa69a9.649708","name":"","func":"\nvar array = [];\nvar i;\nfor (i = 0; i < msg.payload.battery_voltage.length; i++)\n{\n    var listelement =[];\n    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n    listelement[0]=msg.payload.battery_voltage[i].attributes.friendly_name;\n    listelement[1]=msg.payload.battery_voltage[i].state;\n    array[i]=listelement;\n}\nmsg.arr = array;\nreturn msg;\n// for (var index in msg.payload.battery_voltage) {\n//     //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n//     fname = msg.payload.battery_voltage[index].attributes.friendly_name;\n//     state = msg.payload.battery_voltage[index].state;\n//     array[fname] = state;\n// }\n\n// for (var index in msg.payload.battery_size) {\n//     //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n//     array[msg.payload.battery_size[index].attributes.friendly_name + \", \" + msg.payload.battery_size[index].attributes.battery_size] = msg.payload.battery_size[index].state;\n// }\n\n//array.sort((A, B) => B.value - A.value);\n// msg.arr = array;\n// return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1000,"y":540,"wires":[["5b15f94795be9c8a"]]},{"id":"5b15f94795be9c8a","type":"sort","z":"ebaa69a9.649708","name":"","order":"descending","as_num":false,"target":"arr","targetType":"msg","msgKey":"payload","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":1030,"y":660,"wires":[["a25898f22e6e5f71"]]},{"id":"a25898f22e6e5f71","type":"debug","z":"ebaa69a9.649708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1190,"y":640,"wires":[]},{"id":"4bbca37b.1700ec","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

Try this instead and skip the sort node.

var array = [];
var i;
for (i = 0; i < msg.payload.battery_voltage.length; i++)
{
    var listelement =[];
    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);
    listelement[0]=array[msg.payload.battery_voltage[index].attributes.friendly_name];
    listelement[1]=msg.payload.battery_voltage[index].state;
    array[i]=listelement;
}
array.sort();
array.reverse();
msg.arr = array;
return msg;

That does not work either.

But I finally found a way. It’s amazing how hard this is.

What I did was create three arrays two of them with just the battery percentages and one with friendly names.

I sorted one of them with the sort node.
The other two is my translation table where I can lets say take the battery percentage 34, find the index in the unsorted array, then use the index to get the friendly name in the third array.
Then I delete the entry from the two lookup arrays so that I don’t find the same friendly name each time.

[{"id":"5b15f94795be9c8a","type":"sort","z":"ebaa69a9.649708","name":"","order":"ascending","as_num":false,"target":"states","targetType":"msg","msgKey":"payload","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":930,"y":660,"wires":[["83c68abe76f9afd7"]]},{"id":"a8cddac6ea3fe7cb","type":"function","z":"ebaa69a9.649708","name":"","func":"var state = 0;\nvar fname = \"\";\nvar states = [];\nvar states2 = [];\nvar fnames = [];\n\n\nfor (var index in msg.payload.battery_voltage) {\n    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n    fname = msg.payload.battery_voltage[index].attributes.friendly_name;\n    state = msg.payload.battery_voltage[index].state;\n    \n    states.push(state*1);\n    states2.push(state*1);\n    fnames.push(fname);\n}\n\nfor ( index in msg.payload.battery_size) {\n    //node.warn(msg.payload.battery_voltage[index].attributes.friendly_name);\n    \n    fname = msg.payload.battery_size[index].attributes.friendly_name;\n    state = msg.payload.battery_size[index].state;\n    \n    if(!fnames.includes(fname)){\n        states.push(state*1);\n        states2.push(state*1);\n        fnames.push(fname);\n    }\n}\n\n\n\nmsg.states = states;\nmsg.states2 = states2;\nmsg.fnames = fnames;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1000,"y":540,"wires":[["5b15f94795be9c8a"]]},{"id":"83c68abe76f9afd7","type":"function","z":"ebaa69a9.649708","name":"","func":"var states = msg.states;\nvar states2 = msg.states2;\nvar fnames = msg.fnames;\nvar arr = {};\nvar found = 0;\n\nfor( var battpercent in states){\n    found = states2.indexOf(states[battpercent]);\n    if (found > -1) {\n      arr[fnames[found]] = states[battpercent];\n      \n      states2.splice(found, 1);\n      fnames.splice(found, 1);\n    }\n}\n\nmsg.arr = arr;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":720,"wires":[["a25898f22e6e5f71"]]},{"id":"4604e5a18e2e6b34","type":"join","z":"ebaa69a9.649708","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"1","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":850,"y":600,"wires":[["a8cddac6ea3fe7cb"]]},{"id":"a25898f22e6e5f71","type":"debug","z":"ebaa69a9.649708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1190,"y":640,"wires":[]},{"id":"811736146a2f051a","type":"ha-get-entities","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","version":0,"rules":[{"property":"attributes.state_class","logic":"is","value":"measurement","valueType":"str"},{"property":"attributes.device_class","logic":"is","value":"battery","valueType":"str"},{"property":"attributes.battery_voltage","logic":"is","value":".*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":690,"y":620,"wires":[["4604e5a18e2e6b34"]]},{"id":"afd464a52b15da53","type":"ha-get-entities","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","version":0,"rules":[{"property":"attributes.state_class","logic":"is","value":"measurement","valueType":"str"},{"property":"attributes.device_class","logic":"is","value":"battery","valueType":"str"},{"property":"attributes.battery_size","logic":"is","value":".*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":690,"y":560,"wires":[["4604e5a18e2e6b34"]]},{"id":"2da739aba61004d6","type":"change","z":"ebaa69a9.649708","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"battery_voltage","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":620,"wires":[["811736146a2f051a"]]},{"id":"bb78f07125f8413e","type":"change","z":"ebaa69a9.649708","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"battery_size","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":560,"wires":[["afd464a52b15da53"]]},{"id":"eb6da3b4107fbd1a","type":"inject","z":"ebaa69a9.649708","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":600,"wires":[["2da739aba61004d6","bb78f07125f8413e"]]},{"id":"4bbca37b.1700ec","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

No idea why it was that hard, but might I suggest you change your lookup tables into DICTs, since it that DICTs are for.
DICTs are defined with var state2 = {}
and the definition of elements will look like state2[‘ytterdörren power’]=54

That way you can sort your lookup list and use the value like state2[fname[0]]

Besides that you can skip the sort node and just do the sorting in the function node with fname.sort, which sort it ascending. If you want it descending, then you just do a fname.reverse after the sort.

You can’t sort a dict, that is the issue to begin with. There is no such function in Node red

Already established in second post. :slight_smile:

What I was trying to suggest is used DICTs as intended, which is a array with a named key to lookup values.
The have a LIST of the keys in the DICTs that can be sorted.

This works with the caveat that all the numbers are the same amount of spaces. eg (11, 100, 25, 8) will return (100, 11, 25, 8) You could use a filter of <= 99 for the get entities to remove 100. Then as long as something doesn’t go under 10 it should work.

[{"id":"79e47c8f918e7911","type":"inject","z":"f80b6c338afd5483","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"battery\":\"10\",\"battery1\":\"100\",\"battery2\":\"20\",\"battery3\":\"22\",\"battery4\":\"8\"}","payloadType":"json","x":150,"y":2680,"wires":[["598bd26b79556c6b"]]},{"id":"2028885ea35c5470","type":"function","z":"f80b6c338afd5483","name":"","func":"const maxSpeed = msg.payload;\n\nconst sortable = Object.fromEntries(\n    Object.entries(maxSpeed).sort(([,a],[,b]) => a-b));\n\nconsole.log(sortable);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":2680,"wires":[[]]},{"id":"598bd26b79556c6b","type":"debug","z":"f80b6c338afd5483","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":490,"y":2680,"wires":[]}]
const vals = { battery: "10", battery1: "100", battery2: "20", battery3: "22", battery4: "8" };
msg.payload = Object.entries(vals).sort((a, b) => Number(a[1]) - Number(b[1])).reduce((o, key) => ({ ...o, [key[0]]: key[1] }), {})

return msg;