3

I want to loop through different indexed tables by only passing the initial table as an argument. I currently have this table:

local table = {
stuff_1 = {
    categories = {},
    [1] = { 
        name = 'wui',
        time = 300
    }
},
stuff_2 = {
    categories = {'stuff_10', 'stuff_11', 'stuff_12'},
    stuff_10 = {
        categories = {},
        [1] = {
            name = 'peo',
            time = 150
        },
        [2] = { 
            name = 'uik',
            time = 15
        },
        [3] = { 
            name = 'kpk',
            time = 1230
        },  
        [4] = {     
            name = 'aer',
            time = 5000
        }
    },
    stuff_11 = {
        categories = {},
        [1] = { 
            name = 'juio',
            time = 600
        }
    },
    stuff_12 = {
        categories = {},
        [1] = {
            name = 'erq',
            time = 980
        },
        [2] = {
            name = 'faf',
            time = 8170
        }
    }
}

I wanted to make a recursive function to check if the name in any of those tables was equal to some certain thing and return a string. The recursivity lies in the idea of updating this table with whatever ammount I'd like (or until a certain limit). I don't understand exactly what's wrong since when I try:

for k, v in pairs(table) do
    print(k, v, #v.categories)
end 

It correctly prints:

stuff_2 table: 0x10abb0 3
stuff_1 table: 0x10aab8 0

But when passing the table as a parameter to the the function below, it gives this error:

[string "stdin"]:84: attempt to get length of field 'categories' (a nil value)

Function:

function checkMessage(table)
    local i = 1
    local message = ""

    for k, v in pairs(table) do 
        if(#v.categories == 0) then  
            while(v[i]) do 
                if(v[i].name == 'opd') then 
                    if(v[i].time ~= 0) then 
                        message = "return_1"
                    else 
                        message = "return_2"
                    end 
                end 
                i = i + 1 
            end
        else
            checkMessage(table[k])
        end 
    end 
    return message 
end

EDIT: The problem lies in not ignoring that when using pairs onto the table, this doesn't just have tables with a category subtable but it also has a table named category, if this is ignored then the problem is fixed.

1
  • 1
    If you find yourself needing to search tables for names, then you'd better off restructuring your tables to have names as keys, not as values. Commented Sep 30, 2015 at 10:32

1 Answer 1

4

You're recursing into subtables that don't have a categories field. Trying to access categories on them yields nil, which you then try to use the length operator on. Hence your error:

  attempt to get length of field 'categories' (a nil value)

If you can't hand trace your app, put in more print statements or get a line level debugger.

Sign up to request clarification or add additional context in comments.

2 Comments

The question remains though, why don't they have a categories field whilst the subtables of the table passed as argument do? I can also print #v.categories inside the function but can't use it as a conditional.. hmm?
Not all of the subtables do have that field, and it's failing on one that doesn't (e.g. the categories table itself). This was pretty obvious to me looking at your code, but even if you didn't see that by reading, it's the kind of thing a few more print statements and/or a debugger would revealed for you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.