0

I confess feeling little stupid, but after hours of trying I have to ask:

class AGE {

     static func getAge() -> Int {

        var age: Int

        for items in dataArray {
            if items.name == "Steven" {
                age = items.age
            }

            else {
                age = 0
            }
        }

        // variable "age" used before being initialized - WHY?
        return age
    }
}

I even tried to set var age: Int = 0 at the beginning, but then the function return 0. I hope someone could forgive me this basic question at this point. Any help appreciated.

To make it more clear how dataArray looks like:

struct Person {
    let name: String
    let lastName: String
    let age: Int
}

let person1: Person  = Person(name: "Steven", lastName: "miller", age: 23)
let person2: Person = Person(name: "jana", lastName: "drexler", age: 31)
let person3: Person = Person(name: "hanna", lastName: "montana", age: 56)

var dataArray = [Person]()

dataArray.append(person1)
dataArray.append(person2)
dataArray.append(person3)

Update

Trying to assemble the essence of all answers, the solution has to look like this: class AGE {

    static func getAge() ->Int {

        var age: Int = 0

        for items in dataArray {
            while items.firstName == "Steven" {
                age = items.age

                return age

                break       // This break will never be executed because of return.
            }
            break           // setting the break here, the loop will break after first round
        }
        return age
    }
}

This code works, (with the second break) but only for the first loop. The question remaining is, how to set up return and break after the loop hits its target. Either return or break will prevent the other step.

3
  • What is dataArray? Commented Jun 17, 2017 at 12:43
  • Depending on your exact use case, you may want to consider making age optional, returning nil in the case where dataArray is empty. As in such a case, the answer to "what's the age?" is probably not "just been created", rather it's "there is no age". Commented Jun 17, 2017 at 12:53
  • Now i added the dataArray. Commented Jun 17, 2017 at 13:17

5 Answers 5

3

The possible program flow paths leading to the initialization of age before its return are not exhaustive. In case dataArray is empty, the body of the for ... in loop will never be entered, and age will never initialized. The simplest approach to resolve this issue in your particular example would be simply initialize age to 0 upon it's declaration.

Regarding the "unexpected" 0 return even in case dataArray contains an element with a name property valued "Steven": for each pass in the for ... in loop that does not contain an element with a name property valued "Steven", you will reset the value of age to 0. This means that only if the "Steven" valued element is the last of the dataArray will the non-0 age value persist. I don't really see any reason to ever set age to 0 again beyond initialization, so you could resolve this by e.g. performing an early exit (break) from the for loop in case of a match. Alternatively, depending on what you want to achieve, simply return items.last_updated from the method upon first match (just note that early return statements could affect performance).

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

1 Comment

Your answer sounds reasonable. I tried to change the code in your suggested way. The problem which remains is, how to set a break after the return? See new edit.
2

I'm not Swift developer but I doubt these logics are correct. Assuming you initialise age to 0 as suggested in other answers, after you find the element that matches "Steven" into the array, you should exit. Otherwise the next iteration could set age to zero again.

Remember, by default for statement iterates through all elements. If you want to iterate till a condition is met, then a while may be more suitable.

I've read a tutorial and tested this code on line using swift sand box. Sharing my code on this link.

class AGE {
    static func getAge() -> Int {
        var age = 0
        var found = false
        var current = 0
        var allElementsChecked = (dataArray.count == 0) //is false unless array is empty
        while !found && !allElementsChecked {
            found = (dataArray[current].name == "Steven")
            allElementsChecked = (current == dataArray.count-1)
            current += 1
        }
        if found
        {
            age = dataArray[current-1].age //minus 1 to undo last increment within loop 
        }
        return age
    }
}

When comes out from the loop that may be because either "Steven" was found or all elements were checked and not found.

Comments

2

As mentioned in the other answers the issue is that the variable will never be set if the array is empty.

Apart from that your code is inefficient and returns only the expected result if Steven is the last item in the array. Otherwise the variable age gets overwritten with 0.

Nevertheless in Swift there are more convenient methods to filter an item in an array than a repeat loop, for example first(where:

class AGE {

     static func getAge() -> Int {
        return dataArray.first(where: { $0.name == "Steven" })?.age ?? 0
     }
}

or it might be preferable to return nil if Steven is not in the array

class AGE {

     static func getAge() -> Int? {
        return dataArray.first(where: { $0.Name == "Steven" })?.age
     }
}

PS: last_updated in your code is not related to the struct Person at all.

2 Comments

What i´m not understanding: If i´m doing a printout inside the for in loop, the age gets cought. (see my new third code). Doesn´t there have to be a way to get the "age" value thrown out of the function?
Sure, youre right. I corrected. If i´m using the code you suggested, i´m getting error: "Cannot call value of non function type Person"
1

You need to initilize it in the beginning:

var age: Int = 0

If for some reason your for-loop don´t execute then you can´t set your age variable when you only have declared it as var age: Int and not initilized it.

And regarding:

I even tried to set var age: Int = 0 at the beginning, but then the function return 0

That means that you had intilizied your age variable to 0 and the for-loop where never executed and the return will be 0.

4 Comments

so where exactly do i have to initialize var age: Int = 0 ?
Instead of var age: Int do var age: Int = 0
then, i´m getting always 0
Thats because you never enter you for-execution. Try to set a breakpoint within the for-loop.
0

I tested Vadian's answer and it seems to be the correct one as per your requirements.

Nonetheless, here are other suggestions:

First, create another instance of your array based on your Person Struct:

var filteredPerson = [Person]()

If you want to search your dataArray for the age based on the first name:

func getAge(of name: String){
     filteredPerson = dataArray.filter { $0.name == name }
     print (filteredPerson[0].age) }

To get the age value of "Steven":

getAge(of: "Steven")

You'll get the Result: 23.

Note that you can also just get the Int value via return:

func getAge(of name: String) -> Int {
     filteredPerson = dataArray.filter { $0.name == name }
     return filteredPerson[0].age }

On the other hand, if you have lots of Persons in your list with the same name, and you want to get the age value of a specific Person, just add the lastName parameter:

func getAge(name: String, lastName: String){
     filteredPerson = dataArray.filter { $0.firstName == name && $0.lastName == lastName }
     print (filteredPerson[0].age) }

And then get the age value via calling:

getAge(name: "Steven", lastName: "Miller")

Hope this helped someone in some way :)

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.