26

Im learning swift and am having a problem Iterating through an array. Here is what I'm trying to do:

func orderStringByOccurence(stringArray: [String]) -> [String: Int]{
    var stringDictionary: [String: Int] = [:]
    for i in 0...stringArray.count {
        if stringDictionary[stringArray[i]] == nil {
            stringDictionary[stringArray[i]] = 1
            stringDictionary
        } else {
            stringDictionary[stringArray[i]]! += 1
        }
    }
    return stringDictionary
}

I don't get an error until I try to call this function. Then I get this error:

EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0)

I have tried debugging and found that i get the same error when i try this:

for i in 0...arrayFromString.count{
    print(arrayFromString[i])
}

So how do I iterate through this array? Thanks for helping out a new

1
  • Thanks for all the answers Commented Nov 5, 2015 at 20:52

3 Answers 3

36

You need to change

for i in 0...arrayFromString.count

to

for i in 0..<arrayFromString.count

As it is now, you iterate through the array and then one past the end.

You can also use a different style of for loop, which is perhaps a little better:

func orderStringByOccurence(stringArray: [String]) -> [String: Int] {
    var stringDictionary: [String: Int] = [:]
    for string in stringArray {
        if stringDictionary[string] == nil {
            stringDictionary[string] = 1
        } else {
            stringDictionary[string]! += 1
        }
    }
    return stringDictionary
}

Also, you can simplify your logic a bit:

for string in stringArray {
    stringDictionary[string] = stringDictionary[string] ?? 0 + 1
}

Update - For the sake of completeness, I thought I'd add a reduce example here as well. Note that as of Swift 5.1 return statements in single line functions can be implied (SE-0255).

func orderStringByOccurence(stringArray: [String]) -> [String: Int] {
    stringArray.reduce([:]) { result, string in result.merging([string: 1], uniquingKeysWith: +)}
}
Sign up to request clarification or add additional context in comments.

Comments

25

A few more approaches:

let array = ["1", "2", "3"]

You can use forEach with trailing closure syntax:

array.forEach { item in
    print(item)
}

You can use the $0 shorthand:

array.forEach {
    print($0)
}

And if you need the indexes, you can use enumerate():

array.enumerate().forEach { itemTuple in
    print("\(itemTuple.element) is at index \(itemTuple.index)")
}

Comments

7

It seems you're out of index. A more swift-like approach would be in my opinion not to use the count but to do range-based.

var stringArray = ["1", "2", "3"]
for string in stringArray
{
    print(string)
}

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.