How would I pick multiple elements from a table without duplicates?

How could I make a script that picks out a couple of random elements from a table like the one shown below?

local t = {"value", "Another_Value", ["num"] = 1, 2, workspace.Baseplate}
local t = {"value", "Another_Value", ["num"] = 1, 2, 3}

function table.shallow_copy(t)
  local t2 = {}
  for k,v in pairs(t) do
    t2[k] = v
  end
  return t2
end

function table.full_length(t)
    total = 0
    for i,v in pairs(t) do
        if v ~= nil then total+=1 end
    end
    return total
end

function pickRandoms(amount)
  local copy = table.shallow_copy(t)
  local result = {}
  for _ = 1,amount do
    local num = math.random(1,table.full_length(copy))
    local i = 0
    for index,value in pairs(copy) do
        i += 1
        if i == num then
            result[index] = value
            copy[index] = nil
        end
    end
  end
  return result
end

local result = pickRandoms(3)

you could try something like this, it basically picks a random value of the table length using the custom length function since it is a dictionary. It matches it up with a counter to then add the values to a new table and removed them from the cloned version of the original table.

1 Like
local function randomFromDictionary(t, num)
    num = num or 1
    
    local keysList = {}
    for key, _ in pairs(t) do
        table.insert(keysList, key)
    end

    if num>#keysList then num=#keysList end --doesnt make sense to pick more items than there are in the table (since duplicates are not allowed)
    local keys, values = {}, {}
    for i=1, num do
        local selected = table.remove(keysList, math.random(#keysList))
        table.insert(keys, selected)
        table.insert(values, t[selected])
    end
    return keys, values
end

local keys, values = randomFromDictionary(t, 2)

This is my solution to the problem. It basically takes your dictionary and extracts a list of keys. Then I pick random keys and return a pair or lists (a keys, and a values table) that is a randomized subset of t.

it can be made slightly more efficient
local function randomFromDictionary(t, num)
    num = num or 1
    
    local keysList = {}
    for key, _ in pairs(t) do
        table.insert(keysList, key)
    end

    if num>#keysList then num=#keysList end --doesnt make sense to pick more items than there are in the table (since duplicates are not allowed)
    local keys, values = {}, {}
    local cap = #keysList
    for i=1, num do
        local r = math.random(cap)
        local selected = keysList[r]
        keysList[r] = keysList[cap]
        cap = cap - 1
        
        table.insert(keys, selected)
        table.insert(values, t[selected])
    end
    return keys, values
end

local keys, values = randomFromDictionary(t, 2)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.