Thread Tools Display Modes
07-26-17, 07:09 AM   #1
Mortimerlol
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Jul 2017
Posts: 71
Question How print top 5 results only?

Hello to all,

Im sorting a table with ["key"] = value, by (value, key) for do a list with "max. kill numbers - name". This is my code:
Lua Code:
  1. function spairs(BangCharKills, order)
  2.     local tkills = {}
  3.     for k in pairs(BangCharKills) do tkills[#tkills+1] = k end
  4.     if order then
  5.         table.sort(tkills, function(a,b) return order(BangCharKills, a, b) end)
  6.     else
  7.         table.sort(tkills)
  8.     end
  9.     local i = 0
  10.     return function()
  11.         i = i + 1
  12.         if tkills[i] then
  13.             return tkills[i], BangCharKills[tkills[i]]
  14.         end
  15.     end
  16. end
  17. for k,v in spairs(BangCharKills, function(BangCharKills,a,b) return BangCharKills[b] < BangCharKills[a] end) do
  18.    print(v.." - "..k)
  19. end
All is OK but now I need show the first 5 results for make a Top5 but I can't resolv positively. I need do similar to:
Lua Code:
  1. print(v[1], k[1])
  2. print(v[2], k[2])
  3. print(v[3], k[3])
  4. print(v[4], k[4])
  5. print(v[5], k[5])
Thanks for help !
  Reply With Quote
07-26-17, 07:58 AM   #2
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,324
Here's what I came up with. I completely rewrote the sorting algorithm to support names as keys and kill count as values.

Lua Code:
  1. local KillSort;--   Function prototype (Any functions defined with this name will be stored here)
  2. do--    Forced scope enclosure
  3.     local function KVSort(p1,p2)
  4. --      Unpack key/value pairs
  5.         local k1,v1=unpack(p1);
  6.         local k2,v2=unpack(p2);
  7.  
  8. --      Compare values, fallback to keys
  9.         if v1~=v2 then return v1>v2; end
  10.         return k1<k2;
  11.     end
  12.  
  13.     function KillSort(tbl)--    Prototype defined earlier, will store in that upvalue
  14.         local sorttbl={};
  15.         for k,v in pairs(tbl) do table.insert(sorttbl,{k,v}); end-- Scan table and add key/value pairs to sort table
  16.         table.sort(sorttbl,KVSort);--   Sort using our custom function
  17.         return sorttbl;--   Return sorted table (If we returned a reconstructed table with the key/value pairs, they can be randomized again)
  18.     end
  19. end
  20.  
  21. for rank,pair in ipairs(KillSort(BangCharKills)) do
  22.     print(("#%d: %s (%d)"):format(rank,unpack(pair)));--    Print formatted string, "pair" contains a table with key and value
  23.     if rank>=5 then break; end--    Exit loop early if we printed 5 ranks
  24. end

Edit: Fixed KillSort() sorting the wrong table, which surprisingly didn't throw an error trying to unpack() non-tables.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 07-27-17 at 06:21 AM.
  Reply With Quote
07-26-17, 08:13 AM   #3
Mortimerlol
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Jul 2017
Posts: 71
Originally Posted by SDPhantom View Post
Here's what I came up with. I completely rewrote the sorting algorithm to support names as keys and kill count as values.

Lua Code:
  1. local KillSort;--   Function prototype (Any functions defined with this name will be stored here)
  2. do--    Forced scope enclosure
  3.     local function KVSort(p1,p2)
  4. --      Unpack key/value pairs
  5.         local k1,v1=unpack(p1);
  6.         local k2,v2=unpack(p2);
  7.  
  8. --      Compare values, fallback to keys
  9.         if v1~=v2 then return v1>v2; end
  10.         return k1<k2;
  11.     end
  12.  
  13.     function KillSort(tbl)--    Prototype defined earlier, will store in that upvalue
  14.         local sorttbl={};
  15.         for k,v in pairs(tbl) do table.insert(sorttbl,{k,v}); end-- Scan table and add key/value pairs to sort table
  16.         table.sort(tbl,KVSort);--   Sort using our custom function
  17.         return sorttbl;--   Return sorted table (If we returned a reconstructed table with the key/value pairs, they can be randomized again)
  18.     end
  19. end
  20.  
  21. for rank,pair in ipairs(KillSort(BangCharKills)) do
  22.     print(("#%d: %s (%d)"):format(rank,unpack(pair)));--    Print formatted string, "pair" contains a table with key and value
  23.     if rank>=5 then break; end--    Exit loop early if we printed 5 ranks
  24. end
Thanks for the code ^^ but this return unsorted:
Lua Code:
  1. #1: Name 1
  2. #2: otherName 1
  3. #3: oName 3
  4. #4: Namee 2
  5. #5: UnNamed 4
  Reply With Quote
07-26-17, 12:24 PM   #4
Kakjens
A Cliff Giant
Join Date: Apr 2017
Posts: 75
I don't see assignment
BangCharKills = KillSort(BangCharKills)
in line 20
Edit. You might also want to use a function for displaying of results, and not to sort during "for" loop but right before it.

Last edited by Kakjens : 07-26-17 at 12:30 PM.
  Reply With Quote
07-26-17, 12:55 PM   #5
Mortimerlol
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Jul 2017
Posts: 71
Originally Posted by Kakjens View Post
I don't see assignment
BangCharKills = KillSort(BangCharKills)
in line 20
Edit. You might also want to use a function for displaying of results, and not to sort during "for" loop but right before it.
Thanks u so much!
  Reply With Quote
07-27-17, 01:46 AM   #6
Kakjens
A Cliff Giant
Join Date: Apr 2017
Posts: 75
Did that really work? Looking now, I don't see a reason why sorttbl should be updated to reflect the results of sorting.
  Reply With Quote
07-27-17, 06:19 AM   #7
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,324
Originally Posted by Kakjens View Post
I don't see assignment
BangCharKills = KillSort(BangCharKills)
in line 20
Edit. You might also want to use a function for displaying of results, and not to sort during "for" loop but right before it.
The problem with trying to sort BangCharKills directly is that the keys are not numeric. Sorting doesn't work unless they are numeric and sequential. KillSort() returns a sorted list by taking the key/value pairs, enclosing them in tables, and stuffing them as values in the sorting table with sequential indices. As explained before, this is the only way to get sorting to work. The table returned has a completely different structure than the addon uses and is only useful for the for loop, you don't want to overwrite the original table with this.



Originally Posted by Mortimerlol View Post
Thanks for the code ^^ but this return unsorted:
Lua Code:
  1. #1: Name 1
  2. #2: otherName 1
  3. #3: oName 3
  4. #4: Namee 2
  5. #5: UnNamed 4
The problem was in line 16. It's sorting the wrong table, change this to table.sort(sorttbl,KVSort) instead.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 07-27-17 at 06:33 AM.
  Reply With Quote
07-27-17, 06:19 AM   #8
Mortimerlol
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Jul 2017
Posts: 71
Originally Posted by Kakjens View Post
Did that really work? Looking now, I don't see a reason why sorttbl should be updated to reflect the results of sorting.
No, dont work crash my table on savedvariables...
  Reply With Quote
07-27-17, 11:46 AM   #9
Kakjens
A Cliff Giant
Join Date: Apr 2017
Posts: 75
SDPhantom, thanks for explanation. That's why I modify the lines 20 and 21 into
Lua Code:
  1. local mysortedtable = KillSort(BangCharKills)
  2. for rank,pair in ipairs(mysortedtable) do
Also thought that line 16 is suspicious.
By the way, is sorting of full table required? I naively think that the time required to obtain five top-most results should be smaller.
  Reply With Quote
07-27-17, 02:39 PM   #10
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,324
Trying to track the top X entries would be too much work that would ultimately lead to minuscule if any benefit at all. It's entirely possible that the resulting code would have worse performance. If you really want to help it out, you can upvalue unpack() to cut down on global indexing operations. Aside from using the custom comparison function, Lua's C-side sorting algorithm is fairly efficient. If at all possible, you can gain a lot of performance by not defining one, but situations like these require it.

As far as storing the sorted table into a variable, then giving it to ipairs(). This is an extra step that is unnecessary. You're not using the variable anywhere else in the code and it doesn't offer any benefit.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 07-27-17 at 02:45 PM.
  Reply With Quote
07-28-17, 04:52 AM   #11
Kakjens
A Cliff Giant
Join Date: Apr 2017
Posts: 75
I was thinking about something like partial sort instead of full sort.
About making sorted table into variable - was under wrong impression that KillSort(BangCharKills) would be called during for loop. Seems like lua doesn't recalculate the list in which to loop during the loop.
  Reply With Quote
07-28-17, 10:16 AM   #12
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,324
The example you provided is for C code. While it is possible to emulate this in Lua, the performance impacts of doing so is far different. Not only is Lua code far slower than C, but you don't have the same control over memory usage either.



PS: If you're interested in seeing how for...in works, I suggest reading the last half of this section of the Lua manual.
http://www.lua.org/manual/5.1/manual.html#2.4.5
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » How print top 5 results only?


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off