Yeah, I'd probably try the same thing as you did - copy and sort, e.g.:
local top_signals, s = {}
-- Populate and reverse-sort (highest to lowest) top_signals table
for sig, v in pairs(red) do top_signals[#top_signals+1] = {sig=sig, v=v} end
table.sort(top_signals, function(a, b) return a.v > b.v end)
-- Set only current top-5 signals on both output wires
out = {}
for n = 1, 5 do
s = top_signals[n]
if not s then break end
out[s.sig] = s.v
end
Somewhat non-intuitive bit might be the need for nested tables, as table.sort() would need to use top_signals table indexes for ordering.
Also out = {}
is important to flush previous signals there, so that when/if top signal keys change, earlier ones won't be left with their old values.
Didn't test it, but something like that should work.