The limitation of not being able to use the ‘#’ operator to determine the amount of keys in a dictionary is an inconvenience. When running # on a dictionary, it returns 0. It should not return 0. This may be confusing/frustrating for new developers.
I believe it should be built-in behavior for dictionaries to be able to use # so that you don’t need the callback of a function to get how many items are inside.
The work around is to have a function that runs a for loop to count the keys of a dictionary:
local n = 0
for _ in d do -- d being a dictionary
n +=1
end
return n -- gives you the length
Here is a full example of code to test in Studio:
local d = {test1 = 5, test2 = 3} -- this is a dictionary
function countDictionary(d)
local n = 0
for _ in d do
n +=1
end
return n
end
print("this will return 0 since we do #t ", #d)
print("How many items in dictionary: ", countDictionary(d))
It would make my life easier when starting a new project and I believe that new developers could appreciate it as a quick google / devforum search for ‘count dictionary’ comes up with similar for loop code.
This is a backwards-incompatible change and would break many use cases involving mixed tables (mixed array/dictionary) and test functions to check whether something is an array or a dictionary (which currently may use #something == 0 for that).
It could instead be provided as a helper method on table.
This feature request should be retitled to “Tedious to get number of keys in dictionary” because that’s the real problem. Using # specifically for that is a proposed solution, not your problem.
I agree that a more streamlined approach to getting the table size (total amount of keys) that is consistent across any table type would be way better.
Overriding the existing behaviour of # would be terrible for backwards compatibility, but a new method entirely would solve the issue.
Would be nice to avoid having to cache table sizes right next to the table itself.
Is there a chance of the behavior being added to a new function under the table library? I feel like this should be something the language is able to do, it feels counterintuitive to me how it can correctly iterate through a dictionary but can’t count the number of items in it.
The reason it would still be fairly perilous to add as a separate function is that it’s hard to make it clear what the function does: table.keycount… sure, but does it count the array part too? If you pass a table like {1, nil, 2} is the keycount 0, 1, 2, or 3? Using it would also add incompatibility with base Lua to code which might otherwise be portable.
If you really think you want it you don’t actually have to wait for us, you could take action yourself. Under the table library it would be a core Luau feature rather than a Roblox one, so you could open an RFC about it on the Luau Github repo.
I don’t think this is at all unclear, because the number of keys in a lua table is very well defined whether or not the table is an array. table.keycount(tab) should be equivalent to something like #table.keys(tab), and you’d never expect table.keys to only return the array keys. It would be pretty useless if it did. Same logic applies to taking the length of arrays. If we already have #, why would table.keysize return the array length only?
In your particular example, nil is a non-existent value, there is no key 2, so in that case it should return 2. For the same reason that next will never return 2 and pairs will never loop over index 2, that key does not exist. The key doesn’t exist, so, it should never be counted.
print(next({1, nil, 3}, 1)) will print 3 3 because 2 is not the next key.
In other words, it should be equivalent to the following code:
local function tableSize<K, V>(tableToCount: {[K] = V})
local size = 0
for _ in tableToCount do
size += 1
end
return size
end
local d = {test1 = 5, test2 = 3} -- this is a dictionary
function countDictionary(d)
local n = 0
for _ in #d do
n +=1
end
return n
end
print("this will return 0 since we do #t ", #d)
print("How many items in dictionary: ", countDictionary(d))
I thought you needed a # to count number of items inside the table or use ipairs(d)