0

This is a dumb example, but I can't think of the right way to avoid repeating myself when I try to initialize my struct instances below. Notice how they get the same initializer (not sure if that's the right phrase), but what would be another way to do this so i'm giving it a function or something like that instead of the same struct.init(...)?

struct InnerSt {
    var a: String
    var b: String
}

var myStructs: [InnerSt] = []

func assignVal() {
    for item in ["dog", "cat", "fish"] {
        let a: String = "I'm a"
        var pets: String
        let inner: InnerSt = InnerSt.init(a: a, b: item)
        switch item {
        case "dog":
            pets = "hairy"
            //print(inner.a + " " + inner.b + " and I'm " + pets)  //this is like what I want to repeatedly do without the repetition
            myStructs.append(inner) //this works nicely but obviously I miss adding the pets variable
        case "cat":
            pets = "furry"
            //print(inner.a + " " + inner.b + " and I'm " + pets)
            myStructs.append(inner)
        case "fish":
            pets = "scaly"
            //print(inner.a + " " + inner.b + " and I'm " + pets)
            myStructs.append(inner)
        default: ()
        }
    }
}

assignVal()
print(myStructs)
1
  • Seems the two initializer calls are the same, so you coud simply combine the two cases: case 1, 2: Commented Feb 23, 2018 at 5:32

1 Answer 1

0

To avoid writing a bunch of initialisers you could simply change your implementation as follows:

func assignVal() {
    let a = "I'm a "
    for item in [1, 2] {
        let temp = InnerSt.init(a: a, b: item)
        print(temp)
    }
}

Basically, you do not need to switch because item is being assigned as you loop. It will be assigned the value of 1 on the first iteration and 2 on the second.

The benefits are:

  1. The InnerSt initialiser is written once (even though it is called multiple times).
  2. If your array [1, 2] grows (to say [1, 2, 3]) you would not need to add new case to your switch.

A few side notes that helped me in the beginning:

  • InnerSt.init(a: a, b: item) can be shortened to InnerSt(a: a, b: item). Nice for readability.
  • let a: String = "I'm a" can be shorted to let a = "I'm a". Swift has an excellent type inference system. In this case the complier will infer that a is of type String.
  • innserSt would be better named InnerSt. See Apple's excellent guidelines.

Revision after comments

Playground code:

var petsDescriptions: [String] = [] // array of string descriptions of the animals
var pets = ["dog", "cat", "fish", "deer"] // array of all animals

func assignVal() {

    for pet in pets {

        var surfaceFeeling: String = "" // variable to hold the surface feeling of the pet e.g. "hairy"

        switch pet { // switch on the pet
        case "dog":
            surfaceFeeling = "hairy"
        case "cat":
            surfaceFeeling = "furry"
        case "fish":
            surfaceFeeling = "scaly"
        default:
            surfaceFeeling = "<unknown>"
        }

        let description = "I'm \(surfaceFeeling) and I'm a \(pet)" // construct the string description
        petsDescriptions.append(description) // add it to the storage array
    }
}

assignVal()
print(petsDescriptions)

Console output:

["I\'m hairy and I\'m a dog", "I\'m furry and I\'m a cat", "I\'m scaly and I\'m a fish", "I\'m <unknown> and I\'m a deer"]

Let me know if I answered your question correctly or need to add some more information.

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

4 Comments

That's a great idea to append to an array! Actually my use case is more like this, which is why I was using a case statement. I want to do something free form depending on what comes up as the items are iterated:
… func assignVal() { for item in ["dog", "cat", "fish"] { let a: String = "I'm a" var pets: String let inner: InnerSt = InnerSt.init(a: a, b: item) switch item { case "dog": pets = "hairy" print(inner.a + " " + inner.b + " and I'm " + pets). //this is like what I want to do. myStructs.append(inner) //this works fine but obviously I'm missing the 'pets' var getting added like I want …
@ChrisTaylor I have made some revisions. The new code switches on the pet name allowing you to do custom stuff in each case statement. I removed the struct and replaced it with an array of description strings. Let me know if this helps.
Very elegant! Thank you. I will apply this to my use case.

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.