0

I'm looking for the best method to compare a string value entered by the user and compare it to the proper Stage and Level value.

As of now I've made a lot of arrays like so

let Stage1Level1 = ["Phone","Computer,Television"]
let Stage1Level2 = ["Horse","Shoe"]
let Stage1Level3 = ["Milk"]

let Stage2Level1 = ["Snow","Sun"]
let Stage2Level2 = ["Smile","Cry","Water","Salt"]
let Stage2Level3 = ["Five"]

and so on...

So instead of making a long if statement checking for which Stage and Level the user entered I'm looking for the most efficient way of doing this.

Something like this:

var currentStage = 1
var currentLogo = 2

@IBAction func textFieldChanged(_ sender: Any) {

if textFieldChangedOut.text? == Stage(currentStage)Level(currentLogo){

print("Contains the value")

}
}
4
  • 2
    This is very likely the wrong data structure. What are "One" and "Two" in this case? Do they relate to stage and level, or are they two independent strings? Could you have three strings in the array? One string? (If the array has to be a specific length, it probably should not be an array.) Commented Mar 11, 2019 at 13:32
  • @RobNapier "One" and "Two" are just examples of string values the user can enter at the specific Stage and Level. There could be Stage levels that have only one correct value (only one string in the array) and some that have five correct values. So there will not be a specific length of the arrays. My apologies for not making that clear Commented Mar 11, 2019 at 13:37
  • So you have a number of String arrays and the user enters two (?) strings and you want to find the array that contains those strings (or any of the strings?) entered by the user? Commented Mar 11, 2019 at 13:39
  • @JoakimDanielson The user starts by entering a Stage, then continues to select a level. I will then check the "textFieldChangedOut.text?" and wait for the user to write one of the values that specific stageLevelArray contains. Commented Mar 11, 2019 at 13:42

3 Answers 3

3

It's not really clear what these string are, but this is definitely the wrong data structure. I suspect you're looking for something like this, an array of stages that each contain an array of levels, which contain an array of strings.

struct Level {
    var values: [String]
}

struct Stage {
    var levels: [Level]
}

let stages = [
    Stage(levels: [
        Level(values: ["One", "Two"])
        Level(values: ["Horse", "Shoe"]),
        Level(values: ["One", "Two"]),
        ]),
    Stage(levels: [
        Level(values: ["Snow", "Sun"]),
        Level(values: ["Smile", "Cry"]),
        Level(values: ["Five", "Six"]),
        ]),
]

var currentStage = 1
var currentLogo = 2

// Remember that arrays are 0-indexed. If "currentStage" is 1-indexed
// you need to adjust it
let level = stages[currentStage - 1].levels[currentLogo - 1]
let words = level.values

if let text = textFieldChangedOut.text, words.contains(text) {
    print("Contains the value")
}

What you're trying to do with dynamically computing the name of the variable is impossible in pure Swift. There are ways to achieve it by bridging to ObjC, but they're not the right way to attack this problem.

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

3 Comments

This is exactly what I'm looking for! Only problem seems to be that when I enter Stage 1 Level 1 it compares the user input with: "OneTwo". Instead of comparing them individually so that the user input "One" or "Two" is accepted. Should I just solve that by running a for each when doing the comparison?
@Shift if you need to compare with individual values, you have to use contains(_:)
Updated; I was unclear what the == Stage(currentStage)Level(currentLogo) syntax meant.
1

I would create a struct of stage, level and the strings and have an array of that struct

struct StageLevel {
    let stage: Int
    let level: Int
    let words: [String]
}

let stageLevelArray: [StageLevel] = 
    [StageLevel(stage: 1, level: 1, words: ["Hello", "Hi"]), 
    StageLevel(stage: 1, level: 2, words: ["Red", "Blue", "Green"]), 
    StageLevel(stage: 2, level: 1, words: ["No", "Yes"])]

then you can filter out all elements for a chosen stage

let levels = stageLevelArray.filter( { $0.stage == 1} )

or filter out for a stage and a level

let selection = stageLevelArray.filter( { $0.stage == 1 && $0.level == 2 } )

or if you only want the levels or arrays

let levels = stageLevelArray.filter( { $0.stage == 1} ).map { $0.level}
let selection = stageLevelArray.filter( { $0.stage == 1 && $0.level == 2 } ).map { $0.words }

Comments

1

Maybe you can understand adding a dictionary to your current data.

    let Stage1Level1 = ["Phone","Computer,Television"]
    let Stage1Level2 = ["Horse","Shoe"]
    let Stage1Level3 = ["Milk"]

    let Stage2Level1 = ["Snow","Sun"]
    let Stage2Level2 = ["Smile","Cry","Water","Salt"]
    let Stage2Level3 = ["Five"]


    var currentStage = 1
    var currentLogo = 2

    var stageDict : [String: [String]] = [:]


    stageDict["Stage1Level1"] = Stage1Level1
    stageDict["Stage1Level2"] = Stage1Level2
    stageDict["Stage1Level3"] = Stage1Level3
    stageDict["Stage2Level1"] = Stage2Level1
    stageDict["Stage2Level2"] = Stage2Level2
    stageDict["Stage2Level3"] = Stage2Level3


  //You also can build by this way

   [[Stage1Level1, Stage1Level2, Stage1Level3], [Stage2Level1, Stage2Level2,Stage2Level3]]

   .enumerated().forEach{ stage in stage.element.enumerated().forEach{
    stageDict["Stage\(stage.offset+1)Level\($0.offset+1)"] = $0.element
    }
    }

    @IBAction func textFieldChanged(_ sender: Any) {

    if  stageDict["Stage\(currentStage)Level\(currentLogo)"]!.contains(textFieldChangedOut.text!) {
            print("Contains the value")

        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.