Sorting strings with numbers not working properly

table.sort isn’t working right with strings that contain numbers.
Here is an example (don’t pay attention to the letters, just numbers).

list = {"8h","1a","2b","4d","5e","10j","6f","3c","7g","9i"}

What I’m expecting: {"1a","2b","3c",4d","5e","6f","7g","8h","9i","10j"}
What I get: {"1a",10j","2b","3c",4d","5e","6f","7g","8h","9i"} 10 is after 1 and before 2

It even happens in studio itself
image
(these models are sorted by the explorer, not by me)

1 Like

This is because it’s sorting based on the first number. So even though 10 is higher than 9, it’s sorting it based on the 1 in the first digit.

1 Like

I know but is this possible to make it sort like I want?

1 Like

Im not exactly sure if you can, Studio automatically sorts stuff this way so i have no idea

You can probably do #list

1 Like

I just check how many digits the highest number has, and then add zeros to all the smaller numbers until they also have the same number of digits, like:

  • 001 (Lowest)
  • 002
  • 010
  • 011
  • 100
  • 101 (Highest)
1 Like

Is there a method that can do that automatically? In Python it’s zfill

Not to my knowledge, I just use a loop, like this:

local list = {"1Value", "2Value", "3Value" ...}

local highest = nil
for i, v in ipairs(list) do
	if tonumber(v) ~= nil and (highest == nil or tonumber(v) > highest) then
		highest = tonumber(v)
	end
end

for i, v in ipairs(list) do
	if tonumber(v) ~= nil then
		while string.len(tonumber(v) .. "") < string.len(highest .. "") do
			v = "0" .. v
		end
	end
end

(I just wrote this from memory, if it doesn’t work tell me.)

Uhh I think it ran into an infinite loop…

Weird I’ll check it out, and come back to you.

I kind of figured out how to fix the sorting, but this function returns dictionary instead of table
EDIT: nevermind

function sort(tbl)
	local indexes = {}
	
	for i,str in pairs(tbl) do
		local numChar = ""
		
		local number = false
		for _,char in pairs(str:split("")) do
			if tonumber(char) then
				number = true
				numChar ..= char
			else
				if number then
					break --this will sort strings only by their first numbers example a11bbb0 will only be sorted by 11
				end
			end
		end
		indexes[tonumber(numChar)] = str
	end
	local keys = {}
	for k,v in pairs(indexes) do
		table.insert(keys,k)
	end
	table.sort(keys, function(a,b)
		return a < b
	end)
	
	local result = {}
	for i,v in pairs(keys) do
		table.insert(result,indexes[v])
	end
	
	return result
end

(it’s a bit chaotic tbh)

2 Likes

Wait no… it returns a table, I was just trying to get [0] from it. I can’t get used to it

I whole heartedly agree!
Anyways I saw you got an answer, but I will put my fixed code in case anyone wants it:

local function getNumberFromString(str)
	if typeof(str) == "string" then
		return string.gsub(str, "[^0-9]+[A-Za-z0-9]+", function(s) return "" end)
	else 
		return nil
	end 
end

local list = {"1Value", "2Value", "30Value"}

local highest = nil

for i, v in ipairs(list) do
	if getNumberFromString(v) ~= nil and (highest == nil or getNumberFromString(v) > highest) then
		highest = getNumberFromString(v)
	end
end

for i, v in ipairs(list) do
	if getNumberFromString(v) ~= nil then
		while string.len(getNumberFromString(v) .. "") < string.len(highest .. "") do
			v = "0" .. v
		end
		
		--[[
		local val = Instance.new("StringValue")
		val.Name = v
		val.Value = v
		val.Parent = script
		]]
	end
end
1 Like

For future reference, when using numbers to sort names, just put a 0 in front of the number if it’s single digit. 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12

Also this if the numbers will go up to more digits: 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 020, 050, 090, 100. Just add more zeros in front so that all numbers have same digits.

2 Likes

Yes, that’s why we made the above code snippets.