How can I make table.sort work with this table?

I have a table and whenever I try and fetch it, it always returns in a weird order (whenever I try and print it using a for loop):

This is my table:

local Rarity = 
{
    Ancient=0.26;
    Legendary=0.64;
    Mythical=3.2;
    Rare=15.98;
    Uncommon=79.92;
}

I want it to sort from the lowest value to the highest, but for some reason no matter what I do, the last value is always 15.98 instead of 79.92.

This is what I’ve tried doing, but no luck:

local Rarity = 
{
    Ancient=0.26;
    Legendary=0.64;
    Mythical=3.2;
    Rare=15.98;
    Uncommon=79.92;
}

table.sort(Rarity, function(x, y)
    return x > y
end)

for i,v in pairs(Rarity) do
    warn(v)
end

My output:

18:53:57.742 - 0.26
18:53:57.742 - 0.64
18:53:57.743 - 3.2
18:53:57.744 - 79.92
18:53:57.745 - 15.98

Desired output:

0.26
0.64
3.2
15.98
79.92

Would appreciate any help on this:)

Lua dictionaries don’t have and can’t be given an order. You may want to consider making it an array instead.

{
    {"Ancient", 0.26},
    {"Legendary", 0.64},
    -- etc
}

Now you can iterate over it with ipairs or select a value any other way, and your value would be stored in a {name, rarity} pair you can easily access.

Also I should note you want to use ipairs and not pairs on arrays! The latter does not guarantee iteration in order.

4 Likes

I know this is kinda wacky, but I got an idea involving this.

-- Creates a Map with a certain type.  Used in the typeof() function.
-- @classmod Map

-- Class reference
local Array = require("Array")

local Map = {}
Map.ClassName = "Map"

function Map.new(keyType, valueType)
    local self = setmetatable({}, Map)
    
    self._keyType = keyType
    self._valueType = valueType
    
    self._map = {}
    
    return self
end

function Map.fromEntries(entries)
    local self = setmetatable({}, Map)
    
    self._keyType = typeof(entries[1][1])
    self._valueType = typeof(entries[1][2])
    
    self._map = {}

   entries:ForEach(function(index, value)
        self:Add(self._keyType, self._valueType)
    end)
    
    return self
end

function Map:__index(key)
    assert(typeof(key) == self._keyType)
    if self._map[key] then
        return self._map[key]
    else
        return self[key]
    end
end

function Map:__newindex(key, value)
    if not typeof(key) == "nil" then
        assert(typeof(key) == self._keyType)
        assert(typeof(value) == self._valueType)

        self._map[key] = value
    else
        self._map[key] = nil
    end
end

function Map:Add(key, value)
    assert(typeof(key) == self._keyType)
    assert(typeof(value) == self._valueType)

    self._map[key] = value
    return key, value
end

function Map:Get(key)
    if key then
        assert(typeof(key) == self._keyType)
        return self._map[key]
    else
        return self._map
    end
end

function Map:Remove(key)
    assert(typeof(key) == self._keyType)
    self._map[key] = nil
    return key
end

function Map:ForEach(func)
    for key, value in pairs(self._map) do
        func(key, value)
    end
end

function Map:Length()
    return table.getn(self._map)
end

function Map:ToArray()
    local newArray = Array.new(self._keyType)
    
    self:ForEach(function(key, value)
        newArray:Insert(key)
    end)
    
    return newArray
end

function Map:RandomValue()
    local newArray = self:ToArray()
    return self._map:Get()[newArray:RandomValue()]
end

function Map:Entries()
    local entryArray = Map.new("number", "table")
    
    self:ForEach(function(key, value)
        entryArray:Add((entryArray:Length() < 1 and 1 or entryArray:Length()), {key, value})
    end)
    
    return entryArray
end

function Map:Values()
    local valueArray = {}

    self:ForEach(function(index, value)
        table.insert(valueArray, index)
        table.insert(valueArray, value)
    end)

    return valueArray
end

return Map

-- Creates an Array with a type.  Based on the typeof() method.
-- @classmod Array
local Array = {}
Array.ClassName = "Array"

function Array.new(valueType)
    local self = setmetatable({}, Array)
    
    self._valueType = valueType
    self._keyType = typeof(1)
    
    self._array = {}
    
    return self
end

function Array:__index(key)
    assert(typeof(key) == self._keyType)
    if self._map[key] then
        return self._map[key]
    else
        return self[key]
    end
end

function Array:__newindex(key, value)
    if not typeof(key) == "nil" then
        assert(typeof(value) == self._valueType)
        table.insert(self._array, value)
    else
        table.remove(self._array, key)
    end
end

function Array:Get(key)
    if key then
        assert(typeof(key) == self._keyType)
        return self._array[key]
    else
        return self._array
    end
end

function Array:Insert(value, key)
    assert(typeof(value) == self._valueType)
    if not key then
        local key = table.insert(self._array, value)
        return key
    else
        assert(typeof(key) == self._keyType)
        self._array[key] = value
        return key
    end
end

function Array:Remove(key)
    assert(typeof(key) == self._keyType)
    table.remove(self._array, key)
end

function Array:ForEach(func)
    for index, value in pairs(self:Get()) do
        func(index, value)
    end
end

function Array:Length()
    return table.getn(self._array)
end

function Array:Sort(func)
    table.sort(function(a, b)
        func(a, b)
    end)
end

function Array:RandomValue()
    local newRandom = Random.new()
    local randomValue = self[newRandom:NextInteger(1, self:Length())]
    return randomValue
end

function Array:Concat(seperator, start, end)
    local seperator = seperator or ""
    local start = start or 1
    local end = end or self:Length()

    return table.concat(self._array, seperator, start, end)
end

return Array

Way too overcomplicated for a simple task. It’s much easier to use an array with pair-like values.

Did you write this code?

And what exactly is “Array” here?

I agree with @Autterfly, this is way too complex for something so simple.

Yes, array is the second one. It’s overcomplicated but I was trying to make an OOP array and map class. I wanted your approval.