Wow Frank, the hidden patch is so elegant! I'm currently implementing it in my layout, it does exactly what i was looking for. As i could see it shall handle negative numbers just as fine, i hope it does! :) I will report performance soon, I have rather big lists to go through.
Thanks for the great input, Danja
Frank Barknecht wrote: ...
Yes, that's the general idea: You calculate the distance using:
[- 45] | [abs]
and then you look for the smallest distance and use the number(s) of the original list that have this distance as your result.
Attached patch shows several ways to achieve this result. One is using a bunch of abstractions from the [list]-abs collection. First it calculates a distance list made like: x for x in abs(x-45).
For the list: "22 31 47 86" and the comparison value "45" this would be: "23 14 2 41".
Then we find the minimum using [list-minmax] which is 2. Then, using [list-find] we look up the position of 2 in the distance list: It's at index 2 (counting is starting with 0!).
Then finally we retrieve the number at that position in the original list using [list-idx].
This will also find numbers with the same distance.
Another approach is illustrated on the right side of the patch. It doesn't involve any abstractions, but won't find more than one number.
The basic idea is to calculate the distance for every list element, and if that distance is smaller than the distance of the previous element, store the current item in a [f] element at the bottom.
The first item is treated in a special way in that its distance is compared to itself, so that it will always be stored in the lower [f].
Finally when the whole list was consumed, the final result in the lower [f] is bang'd as result. Of course this will only give one result.
And finally, hidden in the subpatch [pd with-list-reduce] is a version that has a functional programming flavour and uses [list-reduce].
[list-reduce] calls whatever functionality you patch and crossconnect to the right oulets on pairs of list items: First on the first and second element, then on the result of that computation and the third element, then on the next result and the fourth element and so on, and finally returns the last result to its left outlet.
In attached patch, the distances of both items in a pair are compared to each other. The number with the smaller distance is sent back to [list-reduce] where it is compared to the next element.
So at first you get a comparison of the distances of 22 and 31 to 45. 31 obviously is closest so next its distance is compared to the distance of the next element, 47. Now 47 is closer, so 47 is sent back to list-reduce which pairs it up with 86. 47 still is closer, and as the list is fully parsed now, 47 is sent to the outlet.
This solution also only returns one result, but personally I think it's the most elegant of the three and looks really neat, if you put the comparision into a subpatch:
[list-reduce]x[pd compare-two]
And I'd always prefer a good looking patch. ;)