57

I'm trying to add a tuple (e.g., 2-item tuple) to an array.

var myStringArray: (String,Int)[]? = nil
myStringArray += ("One", 1)

What I'm getting is:

Could not find an overload for '+=' that accepts the supplied arguments


Hint: I tried to do an overload of the '+=' per reference book:

@assignment func += (inout left: (String,Int)[], right: (String,Int)[]) {
    left = (left:String+right:String, left:Int+right+Int)
}

...but haven't got it right.

Any ideas? ...solution?

9
  • Does append() work? Commented Jun 15, 2014 at 19:09
  • the problem is the optionality of the array Commented Jun 15, 2014 at 19:14
  • 1
    what if you try to overload the operator? Commented Jun 15, 2014 at 19:14
  • still the question why is the array optional? Commented Jun 15, 2014 at 19:18
  • I wanted to add into a nil array, without any previous data. Commented Jun 15, 2014 at 19:19

8 Answers 8

142

Since this is still the top answer on google for adding tuples to an array, its worth noting that things have changed slightly in the latest release. namely:

when declaring/instantiating arrays; the type is now nested within the braces:

var stuff:[(name: String, value: Int)] = []

the compound assignment operator, +=, is now used for concatenating arrays; if adding a single item, it needs to be nested in an array:

stuff += [(name: "test 1", value: 1)]

it also worth noting that when using append() on an array containing named tuples, you can provide each property of the tuple you're adding as an argument to append():

stuff.append((name: "test 2", value: 2))
Sign up to request clarification or add additional context in comments.

4 Comments

The 'append' trick makes the code looks cleaner, but also more confusing... Any logic behind it except for code-cleanliness?
append() feels more useful in cases where i am adding one or a few objects, for code readability...the compound assignment operator, or initializing the array with a set of data, are better adapted for adding a large number of objects at once.
This gives me trouble in Swift 2.0 - Extra argument 'value' in call
@MrBr Try adding parenthesis such as stuff.append((name: "test 2", value: 2))
14

You have two issues. First problem, you're not creating an "array of tuples", you're creating an "optional array of tuples". To fix that, change this line:

var myStringArray: (String,Int)[]? = nil

to:

var myStringArray: (String,Int)[]

Second, you're creating a variable, but not giving it a value. You have to create a new array and assign it to the variable. To fix that, add this line after the first one:

myStringArray = []

...or you can just change the first line to this:

var myStringArray: (String,Int)[] = []

After that, this line works fine and you don't have to worry about overloading operators or other craziness. You're done!

myStringArray += ("One", 1)

Here's the complete solution. A whopping two lines and one wasn't even changed:

var myStringArray: (String,Int)[] = []
myStringArray += ("One", 1)

2 Comments

Of the answers, this one is the simplest and makes the most sense. Overriding operators is something that should rarely be done because those reading the code later will say "WTF". At least in this case it is in the range of the expected over-loadings.
@Zaph: Yep. Everyone went that route because the asker did. But of course, the asker was confused. That's why he was asking. :)
6

Swift 4 solution:

// init empty tuple array
var myTupleArray: [(String, Int)] = []

// append a value
myTupleArray.append(("One", 1))

Comments

3

If you remove the optional, it works fine, otherwise you'll have to do this:

var myStringArray: (String,Int)[]? = nil

if !myStringArray {
    myStringArray = []
}

var array = myStringArray!
array += ("One", 1)
myStringArray = array

You can never append an empty array, so you'll have to initialize it at some point. You'll see in the overload operator below that we sort of lazy load it to make sure that it is never nil.

You could condense this into a '+=' operator:

@assignment func += (inout left: Array<(String, Int)>?, right: (String, Int)) {

    if !left {
        left = []
    }

    var array = left!
    array.append(right.0, right.1)
    left = array

}

Then call:

var myStringArray: (String,Int)[]? = nil
myStringArray += ("one", 1)

Comments

3

I've ended up here multiple times due to this issue. Still not as easy as i'd like with appending onto an array of tuples. Here is an example of how I do it now.

Set an alias for the Tuple - key point

typealias RegionDetail = (regionName:String, constraintDetails:[String:String]?)

Empty array

var allRegionDetails = [RegionDetail]()

Easy to add now

var newRegion = RegionDetail(newRegionName, constraints)
allRegionDetails.append(newRegion)

var anotherNewRegion = RegionDetail("Empty Thing", nil)
allRegionDetails.append(anotherNewRegion)

Comments

1

Note: It's not work anymore if you do:

array += tuple 

you will get error what you need is :

array += [tuple]

I think apple change to this representation because it's more logical

Comments

0
 @assignment func += (inout left: Array<(String, Int)>?, right: (String, Int)) {
    if !left {
        left = []
    }   
    if left {
        var array = left!
        array.append(right.0, right.1)
        left = array
    }
}

var myStringArray: (String,Int)[]? = nil
myStringArray += ("x",1)

Comments

0

Thanks to comments:

import UIKit

@assignment func += (inout left: Array<(String, Int)>?, right: (String, Int)) {
    if !left {
        left = []
    }
    if left {
        var array = left!
        array.append(right.0, right.1)
        left = array
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let interestingNumbers = [
            "Prime": [2, 3, 5, 7, 11, 13],
            "Fibonacci": [1, 1, 2, 3, 5, 8],
            "Square": [1, 4, 9, 16, 25],
        ]

        println("interestingNumbers: \(interestingNumbers)\n")
        var largest = 0

        var myStringArray: (String,Int)[]? = nil

        myStringArray += ("One", 1)

        var x = 0

        for (kind, numbers) in interestingNumbers {
            println(kind)
            for number in numbers {
                if number > largest {
                    largest = number
                }
                x++
                println("\(x)) Number: \(number)")
                myStringArray += (kind,number)
            } // end Number
        } // end Kind
        println("myStringArray: \(myStringArray)")
    }
}

The Output:

interestingNumbers: [Square: [1, 4, 9, 16, 25], Prime: [2, 3, 5, 7, 11, 13], Fibonacci: [1, 1, 2, 3, 5, 8]]

Square
1) Number: 1
2) Number: 4
3) Number: 9
4) Number: 16
5) Number: 25
Prime
6) Number: 2
7) Number: 3
8) Number: 5
9) Number: 7
10) Number: 11
11) Number: 13
Fibonacci
12) Number: 1
13) Number: 1
14) Number: 2
15) Number: 3
16) Number: 5
17) Number: 8



Array of tupules:

myStringArray: [(One, 1), (Square, 1), (Square, 4), (Square, 9), (Square, 16), (Square, 25), (Prime, 2), (Prime, 3), (Prime, 5), (Prime, 7), (Prime, 11), (Prime, 13), (Fibonacci, 1), (Fibonacci, 1), (Fibonacci, 2), (Fibonacci, 3), (Fibonacci, 5), (Fibonacci, 8)]

2 Comments

That still doesn't work. If you try to run it, it will generate a runtime error (if it even compiles) because you never assign an actual value to myStringArray . nil does not mean "an empty array". [] does. See my answer.
This is not an array of tuples but dictionaries.

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.