2
let arrayOfDwarfArrays = [["Sleepy", "Grumpy", "Doc"], ["Thorin", "Nori"]]

var dwarfArray: [String] = []
for dwarfName in arrayOfDwarfArrays {
    dwarfArray.append(dwarfName)
}

All I'm trying to do is access the values of the original array of arrays and append them to a new, single array. But I keep getting this error:

Cannot convert value of type '[String]' to expected argument type 'String'

In the simplest of terms, what am I doing wrong?

3 Answers 3

1

Array.append(_:) expects an argument of type Element, which is only a single element. Obviously, providing a [String] as an argument to this parameter would only work if Element is [String], i.e. if the array had type [[String]]. Since this isn't the case, Array.append(_:) is not the right choice.

Instead, you should use Array.append(contentsOf:), which expects an argument of type S, where S is any Sequence conforming type whose Element is the same as the Array's element. This is suitable for when you want to append all of the elements of a subarray (dwarfName).

let arrayOfDwarfArrays = [["Sleepy", "Grumpy", "Doc"], ["Thorin", "Nori"]]

var dwarfArray: [String] = []
for dwarfName in arrayOfDwarfArrays {
    dwarfArray.append(contentsOf: dwarfName)
}

In this particular case though, this code is even better expressed using a simple Array.flatMap(_:) operation:

let arrayOfDwarfArrays = [["Sleepy", "Grumpy", "Doc"], ["Thorin", "Nori"]]
let dwarfArray = arrayOfDwarfArrays.flatMap { $0 }
Sign up to request clarification or add additional context in comments.

Comments

1

That's happened because dwarfArray is an array of string and expecting a string to be appended. However, it's getting an array of string instead of just string.

Try like this

let arrayOfDwarfArrays = [["Sleepy", "Grumpy", "Doc"], ["Thorin", "Nori"]]

var dwarfArray: [String] = []
for dwarfName in arrayOfDwarfArrays {
    dwarfArray.append(contentsOf: dwarfName)
}

1 Comment

Technically correct, but it's much better to just use append(contentsOf:). For one, it does only resize operation, whereas this code can do any number of resizes.
1

No need to reinvent the wheel. You can use a Sequence instance method called joined(). It will return a FlattenCollection<[[String]]> which you can use to initialise a new array if needed:

let dwarfCollections = [["Sleepy", "Grumpy", "Doc"], ["Thorin", "Nori"]]

// Use 'joined()' to access each element of each collection:
for dwarf in dwarfCollections.joined() {
    print(dwarf)
}

If you need to create a new array just initialize it with the elements of the flatten collection:

let dwarfs = Array(dwarfCollections.joined())  // ["Sleepy", "Grumpy", "Doc", "Thorin", "Nori"]
print(dwarfs)

This will print

Sleepy

Grumpy

Doc

Thorin

Nori

["Sleepy", "Grumpy", "Doc", "Thorin", "Nori"]

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.