Changing entries within a dictionary

How would I go about checking a table (soon to be dictionary) if there are no entries
(EDIT: Changed title to more appropriately reflect the current issue)
for example:

local myDict = {}

for i,v in pairs(myDict) do -- this will never run due to the dictionary having no entries.
--code
end

-- I have also tried the below method

  if not #myDict > 0 then
      myDict["Test"] = 1
  end
-- I would think the above code once ran would give "#myDict" a value of 1 now that it has one entry. But if we were to run this more than once

for i = 1,5,1 do
    if not #myDict > 0 then
        myDict["Test"] = 1
    else
        print("entry exists")
    end
    wait(1)
end

-- you would never see the print "entry exists" as myDict would contiguously = 0, at least this is my experience

Could just make a guard in a for loop:

local isEmpty = true

for i, v in pairs(Dictionary) do
    isEmpty = false
    break
end

if (not isEmpty) then
    ...
end


Could do some crazy stuff with metatables also but that would be overcomplicating it.
Doesn’t really seem efficient but it could work. If there are any other better methods, please do tell me about it.


And why not just check if the key exists? (might be something you’re doing, not sure)

Glad you asked, and yes you’re right it is something I’m doing here. So basically, I’m working on an inventory system. I have multiple slots in a UI for players to be able to select their items etc etc. Essentially, when I go to pick up an item I need to index my table, find an unoccupied slot (a slot with an empty table) and then assign an item to that slot, if an item exists in said slot already, then we simply check if the item matches the item picked up. If so we add a count to our datastore.

So instead of checking for an empty table, you can perhaps just set the empty slot to nil and run a truth statement on it? It would simplify the process a lot and you can always just declare a new table whenever necessary and let the garbage collector do the work

Here is what I’ve tried so far

local myDict = {
["Inventory"] = {
["Hotbar"] = {["Slot1"]={},["Slot2"]={},["Slot3"]={},["Slot4"]={},["Slot5"]={},["Slot6"]={},["Slot7"]={},["Slot8"]={},["Slot9"]={}}
}
}

I can index the above just fine, as long as I set the Slots to tables. If I do as you stated we come up with this

local myDict = {
["Inventory"] = {
["Hotbar"]={["Slot1"]=nil,["Slot2"]=nil,["Slot3"]=nil,["Slot4"]=nil,["Slot5"]=nil,["Slot6"]=nil,["Slot7"]=nil,["Slot8"]=nil,["Slot9"]=nil}
	}
}

which ends up being unable to be indexed as I had originally planned. Here is the code that indexes this table so you can hopefully see what I’m doing

for i,v in pairs(playerdata[player]) do
	for x,y in pairs(v) do
		if x == "Hotbar" then
			for slot,contents in pairs(y) do
				print(slot)
				print(#contents)
				print(contents)
				if contents == nil then
					print("No entry")
					contents[itemname] = 1
				else
					print("Exists")
				end
            end
		end
	end
end				

Forgot to mention, when the table with Slots set to nil is indexed, instead of the “slot” variable of the pairs loop printing “Slot1”,“Slot2”, etc. It instead references by index 1,2,3,4… I need this to be able to print Slot1,Slot2,Slot3… so you can see my issue here

(also the contents variable of the pairs loop would then print the slot name etc)

Since you are using a loop rather than manually indexing for the slots, you can instead use the boolean false to represent empty tables, since nil literally means “doesn’t exist” and thus the loop won’t cover them. By using booleans, the loop will still iterate over them. When you need to use those “empty tables”, you just replace the bool with a newly created table and vice versa.

1 Like

Ahhh okay, I’ll give this a shot.


local defaultstats = {
	["Inventory"] = {
["Hotbar"]={["Slot1"]=false,["Slot2"]=false,["Slot3"]=false,["Slot4"]=false,["Slot5"]=false,["Slot6"]=false,["Slot7"]=false,["Slot8"]=false,["Slot9"]=false}
}
}

-- ^^ playerdata table looks like this per player
local playerdata = {} -- players data gets input here and referenced

-- touched event fires below code
for i,v in pairs(playerdata[player]) do
	for x,y in pairs(v) do
		if x == "Hotbar" then
			print(tostring(x))
			for slot,contents in pairs(y) do
				print(slot)
				print(contents)
				if contents == false then -- Contents always equals false no matter how many times I run this.
					print("No entry")
					contents = nil
					slot = {[itemName] = 1}
					print(slot)
					print(contents)
					break
				else
					print("Exists")
					print(slot)
					print(contents)
					break
				end	
			end
		end
	end
end

I’m getting an issue now, where the slots contents will not override. Even though I clearly redefine the value of “slot”

You didn’t override the slot contents? I don’t see any re-assignment statement

contents = nil
slot = {[itemName] = 1}
contents = slot --missing this?
local defaultstats = {
	["Inventory"] = {
		["Row1"]={
			["Slot1"]={["Empty"]=0},["Slot2"]={["Empty"]=0},["Slot3"]={["Empty"]=0},["Slot4"]={["Empty"]=0},["Slot5"]={["Empty"]=0},["Slot6"]={["Empty"]=0},["Slot7"]={["Empty"]=0},["Slot8"]={["Empty"]=0},["Slot9"]={["Empty"]=0}
		},
		["Row2"]={
			["Slot1"]={["Empty"]=0},["Slot2"]={["Empty"]=0},["Slot3"]={["Empty"]=0},["Slot4"]={["Empty"]=0},["Slot5"]={["Empty"]=0},["Slot6"]={["Empty"]=0},["Slot7"]={["Empty"]=0},["Slot8"]={["Empty"]=0},["Slot9"]={["Empty"]=0}
		},
		["Row3"]={
			["Slot1"]={["Empty"]=0},["Slot2"]={["Empty"]=0},["Slot3"]={["Empty"]=0},["Slot4"]={["Empty"]=0},["Slot5"]={["Empty"]=0},["Slot6"]={["Empty"]=0},["Slot7"]={["Empty"]=0},["Slot8"]={["Empty"]=0},["Slot9"]={["Empty"]=0}
		},
		["Hotbar"]={
			["Slot1"]={["Empty"]=0},["Slot2"]={["Empty"]=0},["Slot3"]={["Empty"]=0},["Slot4"]={["Empty"]=0},["Slot5"]={["Empty"]=0},["Slot6"]={["Empty"]=0},["Slot7"]={["Empty"]=0},["Slot8"]={["Empty"]=0},["Slot9"]={["Empty"]=0}
		}
	}
}

-- Above is a view of the layout of the players data entry and below is the script that SHOULD change the data.

for i,v in pairs(playerdata[player]) do
					if i == "Inventory" then
						for x,y in pairs(v) do -- Check rows in inventory
							local rowFound = false
							if rowFound then
								break
							end
							for slot,contents in pairs(y) do -- Check slots in row
								print(contents)
								local slotFound = false
								if slotFound then
									break
								end
								for item,count in pairs(contents) do -- Check if slot is occupied
									if table.find(contents, itemName) and count < MaxCount then -- if item is in inventory and not at limit
										print("entry not nil")
										count = count+1
										print(slot..":")
										print(contents)
										rowFound = true
										slotFound = true
										return
									elseif item == "Empty" then -- if no items of said type are in inventory
										print("entry nil")
										contents = {[itemName] = 1}
										print(slot..":")
										print(contents)
										rowFound = true
										slotFound = true
										return
									end
								end
							end
						end
					end
				end

so I’ve tried reworking a couple things, and attempted to use table.Create (in a previous attempt) to still no avail. I feel the issue goes deeper than what is shown. As I’m updating the values (the updated values DO get printed to my output) but when I go to pick up another item it cycles back to saying the slot is “empty” and makes my item count 1 over and over, the print(contents) line right after the “for slot,contents in pairs(y) do” loop, prints that the contents are always empty, even though at the: print(slot…":")
print(contents)
lines it shows that the entry was updated. So apparently something else is going on here. Can anyone clarify whats going on? And potential fixes?

Nevermind, I managed to resolve the issue by doing the following:

for i,v in pairs(playerdata[player]) do
			if i == "Inventory" then
				for x,y in pairs(v) do -- Check rows in inventory
					for slot,contents in pairs(y) do -- Check slots in row
						if contents[itemName] and contents[itemName] < MaxCount then -- if item is in inventory and not at limit
							print("entry not nil")
							contents[itemName] = contents[itemName]+1
							return
						elseif contents["Empty"] then -- if no items of said type are in inventory
							print("entry nil")
							table.clear(contents)
							contents[itemName] = 1
							return
						end
					end
				end
			end
		end