Is there a way to sort a table based on sub-strings of the values?

I’ve got a table array of values that I’d like to have ordered based on a numerical value, however - the first character in each value is a letter (which I’d like to ignore.)

For example:

[lua]balls = { “b42”, “i11”, “f23” }[/lua]

I am trying to sort solely by the numbers following the letter, but still return a table that includes said letters, i.e.

[lua]sortedballs = { “i11”, “f23”, “b42” }[/lua]
Thanks to some earlier help I can grab the numbers as substrings easily enough, then use table.sort(test, function(a,b) return tonumber(a) < tonumber(b) end) to sort them - but at that point I’ve lost the letters.

I can’t split it into key/values and sort that, because both the number and/or letter can occur more than once, in which case the key is overwritten using it either way. (there could be “c12” and “d12” which prohibits me from using 12 as a key value, or “c12” and “c15” which would overwrite “c” as an example)

It might be wishful thinking, but is there a way to pass in a function to:

[lua]table.sort(test, function(a,b) return tonumber(a) < tonumber(b) end)[/lua]
so that the sort function compares (a) and (b) as something like:

[lua]string.sub(balls[i], 2)[/lua]
I’ve tried all sorts of newbie things at this point, but I’m still unable to get the desired result (and at this rate I’ll end up with a page full of garbage code to make it happen… if I’m lucky :P) so any pointers are much appreciated if it does indeed need to be torn apart and re-assembled somehow.
Thanks!
[import]uid: 49694 topic_id: 21029 reply_id: 321029[/import]

Thanks Jayant, it certainly does help!

I’m getting an error however, am I messing up the syntax or reference somehow?

[lua]test = { “i11”, “f23”, “b42” }
table.sort(test, function(a,b) return tonumber(string.sub(table[a],2)) > tonumber(string.sub(table[a],2)) end)
print(table.concat(test, ", "))[/lua]

returns the error: "bad argument #1 to ‘sub’ (string expected, got nil)
Not sure if your sample function has placeholders other than ‘test’ for the table I was supposed to change?

Thanks again. [import]uid: 49694 topic_id: 21029 reply_id: 83059[/import]

Thanks again, but I’m still receiving the same error :slight_smile:

[lua]test = { “i11”, “f23”, “b42” }
table.sort(test, function(a,b) return tonumber(string.sub(test[a],2)) > tonumber(string.sub(test[a],2)) end)[/lua]

If I remove the quotes from the original table values I don’t get an error - but then it just makes a blank line when I call

[lua]print(table.concat(test, ", "))[/lua]

afterwards. Any chance that’s related?

Sorry to be such a help vampire, but Google is not my friend on this one.
[import]uid: 49694 topic_id: 21029 reply_id: 83126[/import]

uh, yes, sorry I made a bubu on that one, try

test = { "i11", "f23", "b42" }  
table.sort(test, function(a,b) return tonumber(string.sub(test[a],2)) \> tonumber(string.sub(test[b],2)) end)  

I was trying to illustrate and forgot to substitute the array name, so it remained table…

[import]uid: 3826 topic_id: 21029 reply_id: 83094[/import]

@matthew4,
you can modify your function as

table.sort(test, function(a,b) return tonumber(string.sub(table[a],2)) \> tonumber(string.sub(table[b],2)) end)  

hope that helps,

cheers,

Jayant C Varma
OZ Apps
eMail: dev [at] oz-apps.com
Twitter: @ozapps

Find more information on our
* HowTo site at http://howto.oz-apps.com
* Our upcoming book on using Lua for mobile development [import]uid: 3826 topic_id: 21029 reply_id: 83051[/import]

Thank you, thank you, thank you!

That does the trick. In case someone else ends up reading through there’s a closing ) missing on the print line above, that wasn’t the problem to be solved, just pointing it out as it’ll throw up another error :slight_smile:

When’s that book coming out? [import]uid: 49694 topic_id: 21029 reply_id: 83135[/import]

I cannot believe what I did…

The concept was right, what happens is that when you use the sort function, the function is passed two elements to compare and you are supposed to compare them the way you want and return either a true or a false that indicates if the first value is larger or the second.

what I missed in the earlier code is that the element is already passed, it has been a while since I have been on the forums…

right, so the code is

test = { "i11", "f23", "b42" }  
table.sort(test, function(a,b) return tonumber(string.sub(a,2)) \> tonumber(string.sub(b,2)) end)  
print(table.concat(test,", "))  

a and b are already the elements that you need to parse/extract from. [import]uid: 3826 topic_id: 21029 reply_id: 83131[/import]