Values printing in pairs issue? Lua - arrays

For some reason the countries that seem to be returned are all returning in pairs? How can you change the code so it only returns the countries in 'Europe' once?
function newcountry(continent,country)
local object = {}
object.continent = continent
object.country = country
local list = {}
for i in pairs( object ) do
if object.continent == "Europe" then
table.insert(list, object.country)
print(object.country)
end
end
return object
end
a = newcountry("Africa","Algeria")
b = newcountry("Europe","England")
c = newcountry("Europe","France")
d = newcountry("Europe","Spain")
e = newcountry("Asia","China")

I'm not sure what you are trying to accomplish with this code, but to answer your question:
function newcountry(continent,country)
local object = {}
object.continent = continent
object.country = country
local list = {}
if object.continent == "Europe" then
table.insert(list, object.country)
print(object.country)
end
return object
end
This code will print countries in Europe just once. When there was loop in there, it printed name of the country twice, because it did it for each element of object table (continent and country, hence two times).
Generic for loops in Programming in Lua (first edition).
I would also like to point out that list is quite useless at the moment. It is not being returned and stays local. On top of that, every time you call newcountry there is new list created. They are all unique - country objects are not added to single list. But again - I don't know what you are trying to accomplish.

Related

Rails Ransack, initialize from front end as an array

In the React front end, the ransack parameter is initialized like so:
const statusFilter = 'ransack[status_in]=incomplete';
In the backend, I've got
#params["ransack"]&.each do |filter, value|
so that the first line produces
filter = "status_in"
value = "incomplete"
Everywhere else in the app after initializing, the status_in parameter is used as an array, so that multiple statuses can be selected. So I would like to always treat this parameter as an array, not a string, if possible.
My desired output:
value = ["incomplete"]
I've tried
const statusFilter = "ransack[status_in]=['incomplete']";
But that results in
value = "['incomplete']"
I could probably just check whether the type is a string on the first usage, and then convert it to an array. Something like:
value = [value] if value.class == String
But it seems like there should be a way to accomplish this by slightly changing the front so that I don't need to add another line in the back.

Lua - Why are C functions returned as userdata?

I'm working on game scripting for my engine and am using a metatable to redirect functions from a table (which stores custom functions and data for players) to a userdata object (which is the main implementation for my Player class) so that users may use self to refer to both.
This is how I do my binding in C# in the Player class:
state.NewTable("Player"); // Create Player wrapper table
state["Player.data"] = this; // Bind Player.data to the Player class
state.NewTable("mt"); // Create temp table for metatable
state.DoString(#"mt.__index = function(self,key)
local k = self.data[key]
if key == 'data' or not k then
return rawget(self, key)
elseif type(k) ~= 'function' then
print(type(k))
print(k)
return k
else
return function(...)
if self == ... then
return k(self.data, select(2,...))
else
return k(...)
end
end
end
end");
state.DoString("setmetatable(Player, mt)"); // Change Player's metatable
For my Player class, I implement a method, bool IsCommandActive(string name). When I need to call this method using self, it needs to use the userdata object, rather than the table, otherwise I get the following error:
NLua.Exceptions.LuaScriptException: 'instance method 'IsCommandActive'
requires a non null target object'
For obvious reasons. This is because self refers to the table, not the userdata. So I implemented a metatable so that it may use self to refer to either. The implementation is taken from here, but here is my particular variant (my userdata is stored in an index called data:
mt.__index = function(self,key)
local k = self.data[key]
if key == 'data' or not k then
return rawget(self, key)
elseif type(k) ~= 'function' then
print(type(k))
print(k)
return k
else
return function(...)
if self == ... then
return k(self.data, select(2,...))
else
return k(...)
end
end
end
end
end
Which I follow by using setmetatable, obviously.
Now to the meat of my question. Notice how I print type(k) and print(k) under the elseif. This is because I noticed that I was still getting the same error, so I wanted to do some debugging. When doing so, I got the following output (which I believe is for IsCommandActive):
userdata: 0BD47190
Shouldn't it be printing 'function'? Why is it printing 'userdata: 0BD47190'? Finally, if that is indeed the case, how can I detect if the value is a C function so I may do the proper redirection?
any functions or objects that are part of a C class are userdata`
This is not true. Function is a function, no matter if it's native or written in Lua. Checking the type of a native function would print "function".
It's just it can be that your binding solution is using userdata with __call metamethod set on it, to expose a marshaller with some state/context associated with it. But it doesn't mean that every native function is a userdata, or that every binding lib will be implemented same way. It could be done effectively the same using Lua table instead of userdata. Would you be telling then that "every native function is a table"? :)
After lots of reading about metatables, I managed to solve my problem.
To answer the question in the title, it's apparently what NLua just decides to do and is implementation-specific. In any other bindings, it may very well return as function, but such is apparently not the case for NLua.
As for how I managed to accomplish what I wanted, I had to define the metatable __index and __newindex functions:
state.NewTable("Player");
state["Player.data"] = this;
state.NewTable("mt");
state.DoString(#"mt.__index = function(self,key)
local k = self.data[key]
local metatable = getmetatable(k)
if key == 'data' or not k then
return rawget(self, key)
elseif type(k) ~= 'function' and (metatable == nil or metatable.__call == nil) then
return k
else
return function(...)
if self == ... then
return k(self.data, select(2,...))
else
return k(...)
end
end
end
end");
state.DoString(#"mt.__newindex = function(self, key, value)
local c = rawget(self, key, value)
if not c then
local dataHasKey = self.data[key] ~= key
if not dataHasKey then
rawset(self, key, value)
else
self.data[key] = value
end
else
rawset(self, key, value)
end
end");
state.DoString("setmetatable(Player, mt)");
What __index does is override how tables are indexed. In this implementation, if key is not found in the Player wrapper table, then it goes and tries to retrieve it from the userdata in Player.data. If it doesn't exist there, then Lua just does its thing and returns nil.
And just like that, I could retrieve fields from the userdata! I quickly began to notice, however, that if I set, for instance, self.Pos in Lua, then the Player.Pos would not update in the backing C# code. Just as quickly, I realized that this was because Pos was generating a miss in the Player wrapper table, which meant that it was creating a new Pos field for the table since it actually did not exist!
This was not the intended behavior, so I had to override __newindex as well. In this particular implementation, it checks if the Player.data (userdata) has the key, and if so, sets the data for that particular key. If it does not exist in the userdata, then it should create it for the Player wrapper table because it should be part of the user's custom Player implementation.

as3 check for 2 objects with same property in array

I have an array, lets call it _persons.
I am populating this array with Value Objects, lets call this object PersonVO
Each PersonVO has a name and a score property.
What I am trying to do is search the array &
//PSEUDO CODE
1 Find any VO's with same name (there should only be at most 2)
2 Do a comparison of the score propertys
3 Keep ONLY the VO with the higher score, and delete remove the other from the _persons array.
I'm having trouble with the code implementation. Any AS3 wizards able to help?
You'd better use a Dictionary for this task, since you have a designated unique property to query. A dictionary approach is viable in case you only have one key property, in your case name, and you need to have only one object to have this property at any given time. An example:
var highscores:Dictionary;
// load it somehow
function addHighscore(name:String,score:Number):Boolean {
// returns true if this score is bigger than what was stored, aka personal best
var prevScore:Number=highscores[name];
if (isNaN(prevScore) || (prevScore<score)) {
// either no score, or less score - write a new value
highscores[name]=score;
return true;
}
// else don't write, the new score is less than what's stored
return false;
}
The dictionary in this example uses passed strings as name property, that is the "primary key" here, thus all records should have unique name part, passed into the function. The score is the value part of stored record. You can store more than one property in the dictionary as value, you'll need to wrap then into an Object in this case.
you want to loop though the array and check if there are any two people with the same name.
I have another solution that may help, if not please do say.
childrenOnStage = this.numChildren;
var aPerson:array = new array;
for (var c:int = 0; c < childrenOnStage; c++)
{
if (getChildAt(c).name == "person1")
{
aPerson:array =(getChildAt(c);
}
}
Then trace the array,

Lua - How to check if list contains element

I need some help with my lua script for a game. I need to check if my inventory in the game contains any id from a list.
Here's a piece of my list:
local Game_Items = {
{id = 7436, name = "angelic axe", value = 5000},
{id = 3567, name = "blue robe", value = 10000},
{id = 3418, name = "bonelord shield", value = 1200},
{id = 3079, name = "boots of haste", value = 30000},
{id = 7412, name = "butcher's axe", value = 18000},
{id = 3381, name = "crown armor", value = 12000}
}
The following code might look a bit weird since you don't know what it's for, but it's basically this: the list above is a list of items in my game, and inside the game theres an inventory where you can keep items and stuff. Now I want to check if my inventory contains any of those IDs.
I tried adding 2 of the id's manually and it worked, but my list of items contains over 500 items in total and I don't want to write them all out. Is there a way to put the whole list and check if it's in there somehow?
if not table.contains({ 3035, 3043, Game_Items[id] }, tempItemCounter.id) then
This is what I tried so far. Those two first id's work 3035 and 3043, then I tried all my whole list and only check the Ids. but I dont know how to do that. That code does not work. Could anyone just help me include the whole list of id's in the table.contains ?
Basically wanna include my whole list in that line, without typing out all IDs manually.
Shouldn't Game_Items[id] work? Doesn't that mean all the "id" inside "Game_Items"?
Thanks!
No it doesn't mean that. If foo is a table, then foo[id] looks for a field in foo that is called whatever id refers to, such as a string (so if id is 1 you will get foo[1], if id is "bar" you will get foo.bar, etc).
You can't do it in one line, but you can create a function that will allow you to write your if condition. I'm not sure what tempItemCounter is but assuming that your inventory is a map of keys to entries of the form
inventory = {
[1234] = {....},
[1235] = {....},
...
}
where each integer key is unique, and assuming you want true only if all items are in inventory, then you could do this:
function isAllInInventory(items, inventory)
for i,item in ipairs(items) do
if inventory[item.id] == nil
return false
end
end
return true
end
if isAllInInventory(Game_Items, inventory) then
...
end

Adding items to a multidimensional array without overwriting the old ones?

this may be a simple question, yet I haven't been able to find an answer to it:
How do I add a value to an array without overwriting (all) old values, or having to rewrite them? Is there such a thing as array_push in LUA? And if so, does it work for multidimensional arrays as well?
Example:
Array={"Forest","Beach","Home"} --places
Array["Forest"] = {"Trees","Flowers"} --things you find there
Array["Forest"]["Trees"] = "A tree is a perennial woody plant" --description
If I'd like to add a description of a new thing in a new place, I can't do it using
Array["Restaurant"]["Spoon"] = "A type of cutlery."
because I'd have to declare all these things, as well as the old ones so I don't overwrite them. So I'm looking for something like:
array_push(Array, "Restaurant")
array_push(Array["Restaurant"],"Spoon")
Array["Restaurant"]["Spoon"] = "A type of cutlery."
Thanks!
The following index metamethod implementation should do the trick.
local mt = {}
mt.__index = function(t, k)
local v = {}
setmetatable(v, mt)
rawset(t, k, v)
return v
end
Array={"Forest","Beach","Home"} --places
setmetatable(Array, mt)
Array["Forest"] = {"Trees","Flowers"} --things you find there
Array["Forest"]["Trees"] = "A tree is a perennial woody plant" --description
Array["Restaurant"]["Spoon"] = "A type of cutlery."
Note that you are mixing array indexed values with with string indexed values, and I don't think you intended to do so. For example, your first line stores "Forest" under the key "1", while the second line creates a new table key "Forest" with a table value that holds sequential string values. The following code prints out the generated structure to demonstrate my meaning.
local function printtree(node, depth)
local depth = depth or 0
if "table" == type(node) then
for k, v in pairs(node) do
print(string.rep('\t', depth)..k)
printtree(v, depth + 1)
end
else
print(string.rep('\t', depth)..node)
end
end
printtree(Array)
Next is the resulting output of the two code snippets listed above.
1
Forest
2
Beach
3
Home
Restaurant
Spoon
A type of cutlery.
Forest
1
Trees
2
Flowers
Trees
A tree is a perennial woody plant
With this understanding, you could then solve your problem without such trickery as follows.
Array = {
Forest = {},
Beach = {},
Home = {}
}
Array["Forest"] = {
Trees = "",
Flowers = "",
}
Array["Forest"]["Trees"] = "A tree is a perennial woody plant"
Array["Restaurant"] = {
Spoon = "A type of cutlery."
}
printtree(Array)
The output is then what you probably expected.
Restaurant
Spoon
A type of cutlery.
Beach
Home
Forest
Flowers
Trees
A tree is a perennial woody plant
With all of that in mind, the following accomplishes the same thing, but is much clearer in my humble opinion.
Array.Forest = {}
Array.Beach = {}
Array.Home = {}
Array.Forest.Trees = ""
Array.Forest.Flowers = ""
Array.Forest.Trees = "A tree is a perennial woody plant"
Array.Restaurant = {}
Array.Restaurant.Spoon = "A type of cutlery."
printtree(Array)
First, what you're making is not an array at all, but a dictionary. Try:
T = { Forest = { } , Beach = { } , Home = { } }
T.Forest.Spoon = "A type of cutlery"
Otherwise table.insert may be what you want in array_push
This is almost identically there in standard Lua like this:
Array.Restaurant={}
Array.Restaurant.Spoon={}
Array.Restaurant.Spoon[1]="A type of cutlery."
the table.key notation is equivalent of the table["key"] notation.
Now every item has it's description in the value corresponding to a number-key, and sub items as values corresponding to string keys.
If you really want to have exactly the same syntax as your example, you'll have to use metatables (__index and __newindex methods).

Resources