1

For programmatic reasons, I have a table that looks like the following (note that this is for informational purposes only, please disregard how silly the premise of storing an employee database this way would actually be):

employees =
 {
  john=
   {
    name="john",
    title="Phone Service Representative III",
    salary=17,
    differential=false,
    sched=
     {
      mon={8,"9am-5:30pm"},
      tue={8,"9am-5:30pm"},
      wed={8,"9am-5:30pm"},
      thurs={8,"9am-5:30pm"},
      fri={8,"9am-5:30pm"}
     }
   },
  jack=
   {
    name="jack",
    title="Phone Service Representative II",
    salary=15.50,
    differential=false,
    sched=
     {
      mon={8,"9am-5:30pm"},
      tue={8,"9am-5:30pm"},
      wed={8,"9am-5:30pm"},
      thurs={8,"9am-5:30pm"},
      fri={8,"9am-5:30pm"}
     }
   },
  jane=
   {
    name="jane",
    title="Phone Service Representative I",
    salary=14.25,
    differential=true,
    sched=
     {
      mon={8,"9pm-5:30am"},
      tue={8,"9pm-5:30am"},
      wed={8,"9pm-5:30am"},
      thurs={8,"9pm-5:30am"},
      fri={8,"9pm-5:30am"}
     }
   }
 }

I have a need to be able to call for, for example, employees.john.salary to get a value of 17 to return.

I am running into trouble, however, when I try to write a function to call for a value within one of the entries.

Eventually, I hope to be able to have a separate set of functions that accepts user input, but only if the input is a valid employee, then stores the title associated with the inputted name to be called at a later time with an output of "The "..name.title.." earns "..name.salary.." an hour. \nTheir schedule is as follows: " but I can work out the logic and syntaxes for all of that later, once I understand what I'm doing wrong here.

I tried using a for loop to iterate through looking for values, but wasn't able to get anything I was expecting.

function employees.isemployee(testName)
  local verified=false
  for k,v in ipairs(employees) do
   if v[name]==(testName:lower()) then
     verified=true
   end
  end
  return verified
end

doing a print(employees.isemployee(jane)) returns false, as does print(employees.isemployee("jane")).

I've also tried swapping out ipairs for pairs and spairs, and redoing the loop to:

for testName,v in ipairs(employees) do
  local verified=false
  if v[name]==(testName:lower()) then
...

and to

for k,v in ipairs(employees) do
  if k[name]==(testName:lower()) then
...

and included a print(v.name) in the loop to see what would come out, but all that got me was jackjane.

I was trying to write a function for this rather than using a table.contains() function so that employees.isemployee(jack) can return true, but employees.isemployee("Phone Service Representative II") returns false, and vice-versa for a theoretical istitle() function.

InSync
  • 4,851
  • 4
  • 8
  • 30

1 Answers1

0

In print(employees.isemployee(jane)), jane is recognized as a global variable whose value is nil. Since tables cannot have a nil key, your function correctly returns false. name in v[name] has the same problem. To access the real 'name' key, use either v.name or v['name']. ipairs() is used to iterate over array-like tables. What you want is pairs().

However, fixing these alone won't be enough. We will come back to this later.

Since you already have a hashtable, checking whether it contains a given key does not require iterating over it. Instead, use a ~= nil check:

function employees.isemployee(testName)
  return employees[testName:lower()] ~= nil
end

This function should be used with a string as the only argument, since :lower() is a method of the string "class":

print(employees.isemployee('jane'))  -- true

Do note that, since this employees.isemployee() function is also a member of the table, employees.isemployee('isemployee') returns true. pairs(), if used, will also encounter it and give v this as a value. Functions, however, are not tables and therefore trying to access their .name will result in an ugly error.

InSync
  • 4,851
  • 4
  • 8
  • 30
  • So, to make sure I'm understanding, if I need to check whether a title is valid, I'd use something like ```lua function employees.istitle(testTitle) local isTitle = false for _,v in pairs(employees) do if v['title']==(testTitle:lower()) then isTitle=true end end return isTitle end ``` – Aerotan Lightpaw Jul 19 '23 at 10:30
  • @AerotanLightpaw You need to check for `v`'s type as well: `if type(v) ~= 'function' and v.title == testTitle:lower() then ... end`. – InSync Jul 19 '23 at 10:34
  • Also, your titles as given in the table have uppercase letters. This makes `:lower()` unnecessary and incorrect. – InSync Jul 19 '23 at 10:35