Count

From Pico-8 Wiki
Jump to navigation Jump to search
Important
Previously, this function was considered undocumented and deprecated, but as of version 0.2.4c, it was officially documented, with additional functionality, and is thus safe to use.
count( table, [value] )
Returns the number of elements, or the number of elements with a given value, in the sequence section of a table.
table
The table.

value
The value to search for and count. The default is to count the length of the sequence instead.

return-value
The number of elements with a matching value.

The count() function counts the number of elements in the sequence section of the table in one of two ways:

  1. Counts the number of elements in the sequence, effectively the same as #table, or
  2. Counts the number of elements that match the specified value.

Note that this will not count elements which are outside of the sequence section of the table, and results are undefined if the sequence itself is not well-formed. For example, if t is a "broken" sequence with nil gaps in the middle, count(t) will not deduct the missing nil elements from the count. See the example below for a demonstration of creating, breaking, and fixing sequences.

Note that nil may be passed as a value to search for, and the number of nils within the sequence will indeed be returned, but there are multiple ways that a sequence with nils in the middle can confuse the Lua interpreter and produce misleading results from count(). For example, adding an element farther than #t+1 will not cause Lua to extend the count and neither the new element nor the nils in the gap will be recognized. Thus, the ability to find some nils in a sequence is of limited (and questionable) use.

Examples

-- count the number of times a value occurs in a sequence-style table
t =
{
  "cats",
  "dogs",
  "living",
  "together",
  "mass",
  "hysteria",
  "cool",
  "cats"
}
print(count(t, 'cats'))
--> 2

-- how long is the sequence?
print(count(t))
--> 8

-- does "birds" occur in the sequence?
print(count(t, "birds"))
--> 0         -- sadly, no

-- lua only updates the sequence length when the final element in
-- the sequence, at t[#t], is set to nil, or when a new element is 
-- added immediately after it at t[#t+1]
--
-- let's break the sequence by putting a nil at t[7], which comes
-- before the final element at t[8]:
t[7] = nil    -- 7 == #t-1
print(#t)
--> 8
print(count(t))
--> 8         -- lua did not notice the gap

-- now we can ask how many elements in this broken sequence are broken:
print(count(t, nil))
--> 1         -- oh noes

-- if we also set t[8] to nil, Lua will notice 8 == #t and it will scan
-- the sequence backwards from there until it finds a non-nil element 
-- to update #t and count(t):
t[8] = nil      -- 8 == #t
print(#t)
--> 6
print(count(t))
--> 6

-- see if the sequence is no longer broken
print(count(t, nil))
--> 0           -- yay, it's not broken! well, except, what if...

-- if we add what *seems* like a valid element for this sequence, 
-- but we add it *more* than 1 past the final element at t[6],
-- it will break what we *expect* to be the sequence, and #t and 
-- count(t) will be inconsistent with what we *think* we know:
t[9] = "birds"  -- 9 == #t+3, too far, only #t+1 triggers a recount
print(#t)
--> 6
print(count(t))
--> 6           -- we intuitively expect 9, but that's not how Lua works
print(count(t, "birds"))
--> 0           -- count() does not know we added "birds"

-- t is now an example of where count(t, nil) will *not* detect a
-- broken sequence, because it only looks at t[1 .. #t] and the
-- gap is at 7 and 8, or #t+1 and #t+2
print(count(t, nil))
--> 0           -- we intuitively expect 2, but that's not how Lua works

-- let's try progressively filling the gap so Lua will eventually
-- realize there is an element at t[9]. start by filling t[7]:
t[7] = "for"    -- 7 == #t+1
print(#t)
--> 7
print(count(t))
--> 7           -- we triggered a recount, but Lua stopped at t[8] == nil
print(count(t, "birds"))
--> 0           -- count() still does not know we added "birds"

-- the sequence is still broken, because we have elements beyond #t.
-- let's fill the last remaining gap at t[8]:
t[7] = "the"    -- 8 == #t+1
print(#t)
--> 9
print(count(t))
--> 9           -- we triggered a recount and Lua found both "the" and "birds"
print(count(t, "birds"))
--> 1          -- count() can now find "birds"

-- elements at keys that are not whole numbers >= 1 won't ever be counted:
t[0] = "zero"
print(count(t))
--> 9          -- unchanged; element 0 is never considered part of a sequence
print(count(t, "zero"))
--> 0          -- the search does not scan element 0
t[1.5] = "one point five"
print(count(t, "one point five"))
--> 0          -- 1.5 is not a whole number
t[true] = "true"
print(count(t, "true"))
--> 0          -- booleans are not even numbers
t.ten = 10
print(count(t, 10))
--> 0          -- member notation is technically a string key; no good

See also