Lua Changing Table Keys - lua

Anyone tell me why this doesn't work?
GET_TABLE {1=ID}
key = string.format("%q", GET_TABLE[1])
RETURN_TABLE[key] = "ss"
print(RETURN_TABLE[ID])
print(GET_TABLE[1])
First print result: nil. Second print result: ID
I want the first print result to be: ss
GET_TABLE {1=ID}
key = "ID"
RETURN_TABLE[key] = "ss"
print(RETURN_TABLE[ID])
print(GET_TABLE[1])
The above works fine so I assume its due to the string.format not working right?

The %q format token returns the input as an escaped and quoted Lua string. This means that given the input ID it will return "ID" (the double quotes being part of the string!) which is a different string. (Or, represented as Lua strings, the input is 'ID' and the return value is '"ID"'.)
You have therefore set the ID key while trying to retrieve the "ID" key (which presumably does not exist).
> x = 'ID'
> =x
ID
> =string.format('%q', x)
"ID"
> =#x
2
> =#string.format('%q', x)
4

Your code does not compile (you need [] around the index), and you should use the raw string of ID, not the "quoted" string:
GET_TABLE = {[1]=ID}
key = string.format("%s", GET_TABLE[1])
Note that I had to initialize ID and RETURN_TABLE objects to the following:
ID = 'ID'
RETURN_TABLE = {}
Stylistic note: you should only use all-caps names for constants, otherwise too many makes code hard to read

Related

Why isn't my LUA interpreter able to handle string key values?

When testing code with both a predefined script and the LUA runtime environment, LUA will not take any form of string key values. However, if a numerical value key is used LUA will work with it as intended. The exception to this rule when I am using Tshark with a LUA file to parse packet captures. This allows the string key value syntax to work normally. Is there something I may be performing wrong?
I have tried creating several .lua script files with different variations including:
testArray.NewItem = "value1"
testArray["NewItem"] = "value1"
NewItemValue = "NewItem"
testArray[NewItemValue] = "value1"
These all result in an nil value or an error due to trying to call a nil value depending on the return style used to check.
> tcpstream = {}
> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil
> tcpstream[1] = "nothing"
> print(#tcpstream)
1
> print(tcpstream[1])
nothing
the output of the print(#tcpstream) after the tcpstream[stream1] = "nothing" should show 1 not zero. The subsequent print(tcpstream[1]) should also show "nothing".
From http://lua-users.org/wiki/TablesTutorial
The # operator doesn't count all the items in the table (!). Instead it finds the last integer (non-fractional number) key. Because of how it's implemented its results are undefined if all the integer keys in the table aren't consecutive. Which is why it shouldn't be used for tables used as sparse arrays[2]).
The '#' is not a good(sometimes not correct) way to count the number of elements in Lua table.
As for
> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil
Lua uses key,value pairs, not explicitly index. If you do 'arr[1] = 22', it means the value for the key '1' is 22, not the value for the first element is 22.
The length operator(#) does not work as you believe, this is a common mistake for beginners in Lua.
The default behavior for #sometable is to return the number of consecutive key starting at the number 1(or after any nil value for 5.3). String keys are never evaluated with the default # operator for a table.
In 5.3 if your sequence contains multiple nil values the behavior of # is non-deterministic.
Lua 5.3 Reference Manual: 3.4.7 – The Length Operator
Lua 5.1 Reference Manual: 2.5.5 – The Length Operator
I will include the lines from 5.1 as i feel it covers the information regarding the operator and tables well. While note identical to how 5.3 work it maybe easier to understand why you see the behavior you do.
2.5.5 – The Length Operator
The length operator is denoted by the unary operator #. The length of a string is its number of bytes (that is, the usual meaning of string length when each character is one byte).
The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t1 is nil, n can be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).
Here are some examples of different table and their # results:
table1 = { --number keys in array
true,
true,
true,
}
table2 = { -- number keys in hash
[1] = true,
[2] = true,
[3] = true,
}
table3 = { -- only strings as key
['1'] = true,
['2'] = true,
['3'] = true,
}
table4 = { -- No key 2 defined
[1] = true,
-- [2] = true,
[3] = true,
}
table5 = { -- table with both string and number keys
[1] = true,
['2'] = true,
}
print(#table1) -- 3
print(#table2) -- 3
print(#table3) -- 0
print(#table4) -- v5.3(1 or 3) v5.1(1)
print(#table5) -- 1

Redefine type of variable in Lua

By using Python we can redefine string into dictionary.
Example :
var = "testing"
var = {'body': var}
print var['body']
'testing'
With Lua I want to do same . I want to convert string object into table .
My try :
> var = "testing"
> var = {'body', var}
> print(var)
table: 0x12b2930
> for i,j in pairs(var) do
>> print(i)
>> print(j)
>> end
1
body
2
testing
>
With above example I can fetch testing string with
> print(var[2])
testing
>
Above code is not fulfilling my requirements. I want to store the value 'testing' with "body" key .
I want to fetch like below :
print(var['body'])
'testing'
Please help me on this
var = "testing"
var = {body = var}
print(var.body)
print(var["body"])
Comma in table construction separates table entries. So by specifying {"body", "testing"}, you create two entries with keys 1, 2 that are equal to "body" and "testing", respectively, since that is how you initialise a sequential array.
If you want to assign arbitrary keys to each value, you have to use =, as in {key1 = "body", key2 = "testing"}. Now you can access those elements in two ways. One is object like, using dot:
tab1.key1
And one is array/map like, using square brackets:
tab1["key1"].
In the second example, you have to pay attention to quotes. If you use double quotes, you're accessing a key directly. If not (tab1[key1]), you're using value stored in a variable named key1 as key specifier.
The Lua code closest to the Python code is
var = "testing"
var = {['body'] = var}
print(var['body'])

Lua: implicit table creation with string keys - why the extra brackets?

Say that you want to create a Lua table, and all its keys are valid lua identifiers. Then you can use the key=value syntax:
local niceTable = { I=1, like=1, this=1, syntax=1 }
If however your strings are not "identifiable", then you have to use the ['key']=value syntax:
local operators = { ['*']="Why", ['+']="the", ['/']="brackets", ['?']='?' }
I'm a bit baffled about this. What are those brackets doing there? What do they mean?
They identify the contained string as a key in the resulting table. The first form, you could consider as equal to
local niceTable = {}
niceTable.I = 1;
niceTable.like = 1;
The second form is equal to
local operators = {}
operators['*'] = "Why";
operators['+'] = "The";
The difference is purely syntactic sugar, except where the first one uses identifiers, so it has to follow the identifier rules, such as doesn't start with a number and interpret-time constant, and the second form uses any old string, so it can be determined at runtime, for example, and a string that's not a legal identifier. However, the result is fundamentally the same. The need for the brackets is easily explained.
local var = 5;
local table = {
var = 5;
};
-- table.var = 5;
Here, var is the identifier, not the variable.
local table = {
[var] = 5;
};
-- table[5] = 5;
Here, var is the variable, not the identifier.
The normal syntax for indexing a table is t[val]. For string keys only, Lua provides an alternate syntax, where t.foo is exactly equivalent to t["foo"]. This is purely a syntactical convenience, so-called 'syntax sugar'. It doesn't add functionality, it just gives you a less cluttered syntax for using strings as named fields.
There are a lot of strings keys this won't work for:
t["hello_world"] => t.hello_world -- works
t["hello world"] => t.hello world -- oops, space in the string
t["5 * 3"] => t.5 * 3 -- oops
t['[10]'] => t.[10] -- oops
Basically it only works if the string key would be a valid identifier.
Again, tables are indexed via [], and in most cases you need to use them:
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
["foo"] = 123, -- string key, number value
}
Only if you're using a string key which would work as a valid identifier (no spaces, contains only word characters, numbers, or underlines, and doesn't begin with a number) can you use the shortcut syntax. For the table above, that would be only 'foo':
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
foo = 123, -- string key, number value
}

What would LINQ to Entities return when selecting an integer id for a given row name if the record does not exist?

Here's the code:
string name = "myName";
int id = (int)_myDB.ThingTable.Where(thing => thing.ThingName == name)
.Select(thing => thing.ThingId);
I have an error saying System.Linq.IQueryable cannot be converted to int (I'm assuming it's so that I don't end up with a case where no rows are found- no id is returned)
First, how can I cast it to an int?
Second, what gets returned if no record with a ThingName == name exists?
Thanks,
Matt
You need a query expression that returns a scalar. Something like:
myCollection.Where(c => c.X > 0).FirstOrDefault();
In your example it would be:
int id = (int)_myDB.ThingTable.Where(thing => thing.ThingName == name)
.Select(thing => thing.ThingId).FirstOrDefault();
If no row is returned, the default value of the scalar is returned (generally zero in the case of a non-nullable number).
Try using FirstOrDefault() on queries such as that. It will return the default value for the selection if nothing is returned. 0 for numbers, null for objects.

How to quickly initialise an associative table in Lua?

In Lua, you can create a table the following way :
local t = { 1, 2, 3, 4, 5 }
However, I want to create an associative table, I have to do it the following way :
local t = {}
t['foo'] = 1
t['bar'] = 2
The following gives an error :
local t = { 'foo' = 1, 'bar' = 2 }
Is there a way to do it similarly to my first code snippet ?
The correct way to write this is either
local t = { foo = 1, bar = 2}
Or, if the keys in your table are not legal identifiers:
local t = { ["one key"] = 1, ["another key"] = 2}
i belive it works a bit better and understandable if you look at it like this
local tablename = {["key"]="value",
["key1"]="value",
...}
finding a result with : tablename.key=value
Tables as dictionaries
Tables can also be used to store information which is not indexed
numerically, or sequentially, as with arrays. These storage types are
sometimes called dictionaries, associative arrays, hashes, or mapping
types. We'll use the term dictionary where an element pair has a key
and a value. The key is used to set and retrieve a value associated
with it. Note that just like arrays we can use the table[key] = value
format to insert elements into the table. A key need not be a number,
it can be a string, or for that matter, nearly any other Lua object
(except for nil or 0/0). Let's construct a table with some key-value
pairs in it:
> t = { apple="green", orange="orange", banana="yellow" }
> for k,v in pairs(t) do print(k,v) end
apple green
orange orange
banana yellow
from : http://lua-users.org/wiki/TablesTutorial
To initialize associative array which has string keys matched by string values, you should use
local petFamilies = {["Bat"]="Cunning",["Bear"]="Tenacity"};
but not
local petFamilies = {["Bat"]=["Cunning"],["Bear"]=["Tenacity"]};

Resources