Lua multidimensional table call - arrays

I seem to be having a problem with multidimensional tables (arrays?) on Lua. I have one that looks something like this:
arr =
{
"stats" = {
"23" = {
"1" = {
"account_id" = "10",
"info" = {
"name" = "john"
}
}
}
}
}
and whenever I try to access some info using like:
local entry = "23"
print(arr['stats'][entry]['1'])
or
print(arr['stats'][entry]['1']['info']['name'])
I get nil values, is mixing strings with variables when calling tables even allowed? any idea what I'm doing wrong?

It seems that lua does not accepts things like
arr = { "string" = "value"}
so, either you do
arr = { string = "value"}
or you do
arr = {["string"] = value}
That way, your table must be rewritten as this, in order to run on lua 5.3 interpreter:
arr =
{
stats =
{
["23"] =
{
["1"] =
{
account_id = "10",
info =
{
name = "john"
}
}
}
}
}
doing this, your line
print(arr['stats'][entry]['1']['info']['name'])
runs fine.
Also, it is not good practice to use brackets when you can use a dot. It is not that your script will not run otherwise, but the code gets a lot more legible and easier to debug if you wirte that line like this:
print(arr.stats[entry]['1'].info.name)
Hope that helps...

Related

Search array for a value [swift]

Just started learning swift, spent a few hours trying to figure this out by searching here but no luck so far.
I have an array, created like this:
class ProbabilitiesClass {
var list = [Odds]()
init() {
list.append(Odds(dateInit: -35, oddsTodayInit: "0,01", sevenDaysInit: "0,2"))
list.append(Odds(dateInit: -34, oddsTodayInit: "0,01", sevenDaysInit: "0,3"))
list.append(Odds(dateInit: -33, oddsTodayInit: "0,02", sevenDaysInit: "0,4"))
I want to search first parameter of this array for an integer and return its index.
Tried this
if let i = Odds.firstIndex(where: { $0.hasPrefix(differenceInDays) }) {
print("index is \([i])")
}
It returns error:
Type 'Odds' has no member 'firstIndex'
The end goal is to return second and third parameters of that index.
Update: I defined Odds like this:
import Foundation
class Odds {
let dateText : Int
let oddsToday : String
let odds7Days : String
init(dateInit: Int, oddsTodayInit: String, sevenDaysInit : String) {
dateText = dateInit
oddsToday = oddsTodayInit
odds7Days = sevenDaysInit
}
}
You could do it like so:
let p = ProbabilitiesClass()
let differenceInDays = -34
if let i = p.list.firstIndex(where: { $0.dateText == differenceInDays }) {
print("index is \([i])") //index is [1]
}
Look for the index in the list property of an instance of ProbabilitiesClass. And like the error message says: The class Odds is not an array to use the method firstIndex(where:) on it.
If you want to use the properties of the first element which has its dateInit equal to differenceInDays, then you could do it like so:
if let first = p.list.first(where: { $0.dateText == differenceInDays }) {
print("oddsTodayInit =", first.oddsToday)
print("sevenDaysInit =", first.odds7Days)
}
It uses this function first(where:).

how do i build a list of maps in terraform

i would like to build a list of maps in terraform. Is there an operation that would let me do that.
eg: i would like to build the structure (from aws_instance.test.*.private_ip)
addresses = [
{
address = private_ip-1
},
{
address = private_ip-2
}
...
]
Apologies if this has already been resolved, I see that it's an older question.
I'm not sure if this is best practice, but this is the way I would attempt to reach the desired state.
Using the null_resource you'd be able to do the following:
variable "addresses" {
type = "list"
default = [
"private_ip-1",
"private_ip-2",
"private_ip-3"
]
}
resource "null_resource" "test" {
count = "${length(var.addresses)}"
triggers {
address = "${element(var.addresses, count.index)}"
}
}
output "addresses" {
value = "${null_resource.test.*.triggers}"
}
And have this output:
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
addresses = [
{
address = private_ip-1
},
{
address = private_ip-2
},
{
address = private_ip-3
}
]
I'm currently on terraform 0.11.5, null_resource appears to have been added in 0.6.7
There are limitations to the null_resource triggers though. interpolated variables can only result in strings. So, unfortunately you won't be able to interpolate a value that would result in a list or a map; for example:
resource "null_resource" "test" {
triggers {
mylist = "${var.addresses}"
}
}
will result in an error
Error: null_resource.test: triggers (address): '' expected type 'string', got unconvertible type '[]interface {}'
With terraform 10.8 you can
output "private_subnets" {
value = [
"${aws_subnet.private.*.id}"
]
}
https://github.com/hashicorp/terraform/issues/7430

Search and use of Strings in 2D Arrays

I got a 2D array where I want to fetch data from the 2nd dimension based on the 1st, but I dont understand how to set it up in Swift 2 since the old for-loop function is deprecated.
Based on the name (Burt) I want to present the phone-No and Group.
myArray: [[String]] = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]
For i in 0..myArray.count {
If myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
  GroupNoLabel.text = myArray[i][2]
}
}
This is how I solved it with the help of Tarun Seera.
let myArray = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]]
var user: String = "Burt"
var phoneNo: String = ""
var groupNo: String = ""
for i in myArray {
if i[0] == user {
phoneNo = i[1]
groupNo = i[2]
}
}
You can also make entities (NSObject)array and use predicate to achieve the same thing and still if you want this form 2d array you can use below code
let myArray = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]]
for i in myArray {
if i[0] == "Burt" {
print("Hurrey I am in.. my name is: \(i[0]) my Id is:\(i[1]) and my gourp is:\(i[2])")
}
}
for i in 0..<myArray.count {
if myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
GroupNoLabel.text = myArray[i][2]
}
}
Use
..<
instead of just
..
Your problem is, that i is going from 0 to myArray.count - which is 4 .. that means your i is going 0,1,2,3,4 = you have 5 times i. Your array only has 4 "items".
for i in 1...myArray.count{
if myArray[i-1][0] == "Burt" {
phoneNoLabel.text = myArray[i-1][1]
GroupNoLabel.text = myArray[i-1][2]
}
}
or
for i in 0...myArray.count-1{
if myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
GroupNoLabel.text = myArray[i][2]
}
}
should solve your problem.
As an alternative to explicit looping, you could use a functional programming approach
let searchForUser = "Burt"
let userInfo = Array(myArray
.flatMap{ $0.first == searchForUser ? $0.suffixFrom(1) : nil }
.flatten())
print(userInfo) // ["251436", "Group2"]
For you specific example, the user info you're after is readily obtainable from the userInfo array
phoneNoLabel.text = userInfo[0] // 251436
groupNoLabel.text = userInfo[1] // Group2
Note here that I've renamed GroupNoLabel variable (UILabel?) from the example in your question to groupNoLabel, as variables in Swift should, by convention, use camelCase names (and not CamelCase, as is used e.g. for types).

Run a function that is stored in an array - Swift

I have recently started coding for iOS and using Swift. I am trying to build a small quiz app for practice. However, I am having an issue running a function that is stored in an array.
My question library swift file is as follows:
func getQuestionLibrary() -> NSArray {
var questionLibrary = [
[
"categoryName": "General Knowledge",
"functionName": generalknowledgeLibrary()
]]
As you can see it states the category and stores a function.
My code that works fine, uses this array (there are more entries) to dynamically create a list of categories to choose from. When a category is run it performs a segue and moves onto a view to display the categories.
If I hard code in the categories that app works great:
if playQuestionLibraryText == "General Knowledge" {
questionPack = generalknowledgeLibrary()
} else if playQuestionLibraryText == "Music" {
questionPack = musicLibrary()
} else if playQuestionLibraryText == "Film" {
questionPack = filmLibrary()
}
However, as the list is dynamic I would prefer it not to be hard coded.
Please can you assist me to allow the my code to search the array and run the function stored as functionName in the array when the correct category has been selected.
Thank you in advance.
The code:
"functionName": generalknowledgeLibrary()
Sets "functionName" to the result of calling the function.
Use:
"functionName": generalknowledgeLibrary
You are looking up a 'library' based on its name; use a Dictionary. Your 'library' is going to hold some stuff (as libraries are wont to do) and allow some behaviors - so capture it as an abstraction.
class Library { // maybe this is a 'questionPack'
// stuff in a library // that is okay, change the name
}
var libraryMap : [String:Library] =
["Music": Library(/*...*/),
"Film" : Library(/*...*/),
"General Knowledge" : Library(/*...*/)
// ....
]
if let library = libraryMap[playQuestionLibraryText] {
// do something with the library
}
i did a code to this question, using subscript
I created a class collection to manage your question. I believe the friend solution just remove () is more easy and correctly, but i created this class to complement my studies, because this I like enter here to try new solutions.
class QuestionCollection
{
struct QuestionItem {
var categoryName:String;
var function:()->Void //Here can add return type you need
}
private var dicCallbacks:[String:QuestionItem] = [String:QuestionItem]();
func add(categoryName:String, closure:()->Void //Here can add return type you need )
{
dicCallbacks[categoryName] = QuestionItem(categoryName: categoryName, function: closure);
}
subscript(categoryName:String)->()->Void //Here can add return type you need
{
get
{
if let callback = self.dicCallbacks[categoryName]
{
return callback.function;
}
return error;
}
set
{
dicCallbacks[categoryName] = QuestionItem(categoryName: categoryName, function: newValue);
}
}
func error()->Void
{
println("error try catch closure function")
}
}
How use this class
func musicTest()
{
println("test Music");
}
func musicGK()
{
println("test Music");
}
func musicFilm()
{
println("test Music");
}
var questionCollection = QuestionCollection();
questionCollection["Music"] = musicTest
questionCollection["General Knowledge"] = musicGK
questionCollection["Film"] = musicFilm
questionCollection["Music"]();
questionCollection["General Knowledge"]();
questionCollection["Film"]();
Sorry for slow reply. I changed my code as this works instead and I am happy with how it works.
The questions in the future will be populated via the internet via a loop.
struct Question {
var categoryName : String
var questionTitle : String
var answerA : String
var answerB : String
var answerC : String
var answerD : String
var correct : String
}
public struct QuestionLibrary {
var questions: [Question]
}
let QuizQuestions =
QuestionLibrary(
questions: [
Question(
categoryName: "General Knowledge",
questionTitle: "Question 1",
answerA: "A", answerB: "B", answerC: "C", answerD: "D", correct: "D"),
Question(
categoryName: "Music",
questionTitle: "Question 2",
answerA: "A", answerB: "B", answerC: "C", answerD: "D", correct: "A"),
Question(
categoryName: "Film",
questionTitle: "Question 3",
answerA: "A", answerB: "B", answerC: "C", answerD: "D", correct: "B")
])
My code then to retrieve questions based on the category is:
let questionLibrary = QuizQuestions.questions
var questionPack: Array<Question>?
questionPack = questionLibrary.filter({c in c.categoryName == "Music" })
I then select a random question
let question = questionPack![randomNumber]
And to display the question text is
question.questionTitle
So, my earlier question was about running functions in an array which I learnt I didn't need to do. But least I've answered so it might have others who need similar code :)

Groovy ConfigSlurper Configure Arrays

I am trying to create a config that would look something like this:
nods = [
nod {
test = 1
},
nod {
test = 2
}
]
and then use configSlurper to read it but the "node" objects appear to be null after the read.
Here is my code:
final ConfigObject data = new ConfigSlurper().parse(new File("config.dat").toURI().toURL())
println data.nods
and the output:
[null, null]
What am I doing wrong?
Thanks!
It think I resolved it this way:
config {
nods = [
['name':'nod1', 'test':true],
['name':'nod2', 'test':flase]
]
}
And then using it like:
config = new ConfigSlurper().parse(new File("config.groovy").text)
for( i in 0..config.config.nods.size()-1)
println config.config.nods[i].test
Hope this helps someone else!!
You have to be careful when using ConfigSlurper when doing this sort of thing.
For example your solution will actually produce the following output:
true
[:]
If you look carefully you will notice that there is a typo on the second array value flase instead of false
The following:
def configObj = new ConfigSlurper().parse("config { nods=[[test:true],[test:false]] }")
configObj.config.nods.each { println it.test }
should produce the correct result:
true
false
I tried to parse with ConfigSlurper something like this:
config {sha=[{from = 123;to = 234},{from = 234;to = 567}]}
The array "sha" was far from what expected.
To get "sha" as an array of ConfigObjects I used a helper:
class ClosureScript extends Script {
Closure closure
def run() {
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.delegate = this
closure.call()
}
}
def item(closure) {
def eng = new ConfigSlurper()
def script = new ClosureScript(closure: closure)
eng.parse(script)
}
this way I get an array of ConfigObjects:
void testSha() {
def config = {sha=[item {from = 123;to = 234}, item {from = 234;to = 567}]}
def xx = item(config)
assertEquals(123, xx.sha[0].from)
}

Resources