Thread Tools Display Modes
02-23-13, 07:26 AM   #1
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Checking a value against every value in a table

Back with another LUA question:

I am interested if LUA inherently supports checking a value against ANY value in a table. Let me explain.

Let us say we have a table with some values:

Lua Code:
  1. local myTable = {
  2.     "Value1",
  3.     "Value2",
  4.     "Value3"
  5. }

Is there any way I can check some variable against the whole table as in:

Lua Code:
  1. if some variable == ANY value in myTable then code here end

I am curious because using a
Lua Code:
  1. for k, v in pairs(myTable)
loop seems a bit bulky just to decide if the variable matches any value in said table.

Thank you for your time and assistance!

Last edited by Clamsoda : 02-23-13 at 07:33 AM.
  Reply With Quote
02-23-13, 08:01 AM   #2
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
Your table is an indexed table; every value is automatically assigned an index number. Any kind of 'contains' function will use either a loop or a search algorithm to find the correct value.

If you set it up like this:

Code:
local myTable = {
    ["Value1"] = true,
    ["Value2"] = true,
    ["Value3"] = true,
}
Then you have a key-value table where your previous values serve as keys and the value is always true, so you can perform a lookup like this:

Code:
if myTable[someVariable] then ...
  Reply With Quote
02-23-13, 08:33 AM   #3
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Well, perhaps I should delve a bit deeper into what I am striving for. Let us say that I have an input that may have ANY value. I want to check this against a table of any possible value that may be considered valid. Let me set up a few examples:

local input = "Haleth"

local table = {
"Phanx",
"Clamsoda",
"Seerah",
"Dridzt",
"Haleth"
}

What I would like to do is construct an IF statement that if the input is ever ANY value that is in said table, that we may proceed with the code. And this process will remain true for any amount of values I add to, or remove from the table, and is independent of the input value. The input may become "apple", or "seven", in which case it wouldn't match, unless "apple" or "seven" was added to the table. Additionally, if I removed "Haleth" from the table the input would no longer be true.

I am very sorry if I missed your point, or not illustrating mine correctly.
  Reply With Quote
02-23-13, 08:45 AM   #4
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Haleth's example is how you do this unless you have some reason not to just use the value you're looking up as the key, like if the values aren't unique, and even then if the table is large enough you might consider constructing a lookup table.
  Reply With Quote
02-23-13, 08:50 AM   #5
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Ahh, I do believe that I read Haleth's post too quickly, and this his solution will be perfect. I have been up and at this for....some time, so excuse the mistake.

Thank you much for the input!

Edit: Working perfectly, thank you for your input Haleth, and for making me re-read it Semlar.

Last edited by Clamsoda : 02-23-13 at 09:00 AM.
  Reply With Quote
02-23-13, 12:30 PM   #6
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,359
I understand that you solved your problem by altering your table from an array style table to a hash style table.

However for others that might stumble on this thread I'll add that Blizz has implemented a global function in UIParent that allows checking for the existence of a value in an array style table.
Code:
local exists = tContains(table, value)
checks if table contains value, table being of type {[1]=value1, [2]=value2,...,[n]=valuen} or {value1, value2,..., valuen}
  Reply With Quote
02-23-13, 12:49 PM   #7
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Wouldn't this just be a wrapper for the pairs() loop?
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
02-23-13, 01:03 PM   #8
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
The tContains function is implemented like this:

Code:
function tContains(table, item)
       local index = 1;
       while table[index] do
               if ( item == table[index] ) then
                       return 1;
               end
               index = index + 1;
       end
       return nil;
end
So yes, it also uses a loop.
  Reply With Quote
02-23-13, 01:08 PM   #9
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
*nod*

But thanks for that, Dridzt. It's useful if you don't want to (or can't) change your table structure and would rather use the wrapper function.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
03-04-13, 09:52 PM   #10
Xinhuan
A Chromatic Dragonspawn
 
Xinhuan's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 174
Originally Posted by Clamsoda View Post
Well, perhaps I should delve a bit deeper into what I am striving for. Let us say that I have an input that may have ANY value. I want to check this against a table of any possible value that may be considered valid. Let me set up a few examples:

local input = "Haleth"

local table = {
"Phanx",
"Clamsoda",
"Seerah",
"Dridzt",
"Haleth"
}

What I would like to do is construct an IF statement that if the input is ever ANY value that is in said table, that we may proceed with the code. And this process will remain true for any amount of values I add to, or remove from the table, and is independent of the input value. The input may become "apple", or "seven", in which case it wouldn't match, unless "apple" or "seven" was added to the table. Additionally, if I removed "Haleth" from the table the input would no longer be true.

I am very sorry if I missed your point, or not illustrating mine correctly.
You could restructure your table to:

local table = {
"Phanx" = 1,
"Clamsoda" = 1,
"Seerah" = 1,
"Dridzt" = 1,
"Haleth" = 1
}

If you add Phanx to the table, you would do
table["Phanx"] = (table["Phanx"] or 0) + 1

Checking if it exists is just

if (table["Phanx"]) then ...

The key is the string, and the value is the number of times it is added to the table. This method would obviously not work if you need the table to be sorted in a particular order instead.
__________________
Author of Postal, Omen3, GemHelper, BankItems, WoWEquip, GatherMate, GatherMate2, Routes and Cartographer_Routes
  Reply With Quote
03-05-13, 12:22 AM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Yes, but your syntax is bad, Xin. You must be rusty from all that time away!

This works:
Code:
local tbl = {
    ["Phanx"] = 1,
    ["Clamsoda"] = 1,
    ["Seerah"] = 1,
    ["Dridzt"] = 1,
    ["Haleth"] = 1,
}
And this works, for strings containing only letters, numbers, and underscores:
Code:
local tbl = {
    Phanx = 1,
    Clamsoda = 1,
    Seerah = 1,
    Dridzt = 1,
    Haleth = 1,
}
But this will raise an error, because you can't use strings that way:
Code:
local tbl = {
    "Phanx" = 1,
    "Clamsoda" = 1,
    "Seerah" = 1,
    "Dridzt" = 1,
    "Haleth" = 1,
}
On a side note, please never, ever name your table "table" -- that's already a global defined by WoW Lua, and is a table containing table-related functions, like table.insert, table.remove, table.sort, etc. More generally, you should never give anything the same name (even if it's local) as a global Lua function/object or a global WoW API function (eg. UnitName) or a global WoW UI object (eg. ChatFrame1). If your variable gets leaked into the global namespace, you will break other addons and/or the Blizzard UI and/or the UI in general. Even if it stays local, it's still just creating unnecessary confusion -- when you look at a part of your code using the variable, you have to figure out whether that code is referring to your local thing or the global thing with the same name -- and is a bad habit to be in.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-05-13, 12:26 AM   #12
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
They were general examples that I hand wrote in the message box. All of my variables have lengthy, well descriptive names.
  Reply With Quote
03-05-13, 12:39 AM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Yes, but your "general examples" get copied and pasted as literal examples of working code by novices who don't know any better.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-05-13, 12:42 AM   #14
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Touché, touché.

Also, thank you everyone for the input, it truly did help me get to where I wanted to be with my AddOn.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Checking a value against every value in a table

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off