Append an array of strings to a string in Swift - ios

I have an array of strings for one variable, and a string as another variable. I'd like to append all of the strings in the collection to the single string.
So for example I have:
var s = String()
//have the CSV writer create all the columns needed as an array of strings
let arrayOfStrings: [String] = csvReport.map{GenerateRow($0)}
// now that we have all the strings, append each one
arrayOfStrings.map(s.stringByAppendingString({$0}))
the line above fails. I've tried every combination I can think of, but at the end of the day, I can't get it unless I just create a for loop to iterate through the entire collection, arrayOfStrings, and add it one by one. I feel like I can achieve this the same way using map or some other function.
Any help?
Thanks!

You can use joined(separator:):
let stringArray = ["Hello", "World"]
let sentence = stringArray.joined(separator: " ") // "Hello World"

You could convert your array to string using joinWithSeparator(String)
here is an example
var array = ["1", "2", "3"]
let stringRepresentation = array.joinWithSeparator("-") // "1-2-3"
source: [ How do I convert a Swift Array to a String? ]

There are at least two options here. The most semantic choice is likely joinWithSeparator on the [String] object. This concatenates every string in the array, placing the separator provided as a parameter between each string.
let result = ["a", "b", "c", "d"].joinWithSeparator("")
An alternative is to use a functional reduce and the + function operator which concatenates strings. This may be preferred if you want to do additional logic as part of the combine. Both example code produce the same result.
let result = ["a", "b", "c", "d"].reduce("", combine: +)
It's also worth noting the second options is transferrable to any type that can be added, whereas the first only works with a sequence of strings, as it is defined on a protocol extension of SequenceType where Generator.Element == String.

Related

Index out of array in array with classes [duplicate]

Suppose I have an array, for example:
var myArray = ["Steve", "Bill", "Linus", "Bret"]
And later I want to push/append an element to the end of said array, to get:
["Steve", "Bill", "Linus", "Bret", "Tim"]
What method should I use?
And what about the case where I want to add an element to the front of the array? Is there a constant time unshift?
As of Swift 3 / 4 / 5, this is done as follows.
To add a new element to the end of an Array.
anArray.append("This String")
To append a different Array to the end of your Array.
anArray += ["Moar", "Strings"]
anArray.append(contentsOf: ["Moar", "Strings"])
To insert a new element into your Array.
anArray.insert("This String", at: 0)
To insert the contents of a different Array into your Array.
anArray.insert(contentsOf: ["Moar", "Strings"], at: 0)
More information can be found in the "Collection Types" chapter of "The Swift Programming Language", starting on page 110.
You can also pass in a variable and/or object if you wanted to.
var str1:String = "John"
var str2:String = "Bob"
var myArray = ["Steve", "Bill", "Linus", "Bret"]
//add to the end of the array with append
myArray.append(str1)
myArray.append(str2)
To add them to the front:
//use 'insert' instead of append
myArray.insert(str1, atIndex:0)
myArray.insert(str2, atIndex:0)
//Swift 3
myArray.insert(str1, at: 0)
myArray.insert(str2, at: 0)
As others have already stated, you can no longer use '+=' as of xCode 6.1
To add to the end, use the += operator:
myArray += ["Craig"]
myArray += ["Jony", "Eddy"]
That operator is generally equivalent to the append(contentsOf:) method. (And in really old Swift versions, could append single elements, not just other collections of the same element type.)
There's also insert(_:at:) for inserting at any index.
If, say, you'd like a convenience function for inserting at the beginning, you could add it to the Array class with an extension.
Use += and + operators :
extension Array {
}
func += <V> (inout left: [V], right: V) {
left.append(right)
}
func + <V>(left: Array<V>, right: V) -> Array<V>
{
var map = Array<V>()
for (v) in left {
map.append(v)
}
map.append(right)
return map
}
then use :
var list = [AnyObject]()
list += "hello"
list += ["hello", "world!"]
var list2 = list + "anything"
Here is a small extension if you wish to insert at the beginning of the array without loosing the item at the first position
extension Array{
mutating func appendAtBeginning(newItem : Element){
let copy = self
self = []
self.append(newItem)
self.appendContentsOf(copy)
}
}
In Swift 4.1 and Xcode 9.4.1
We can add objects to Array basically in Two ways
let stringOne = "One"
let strigTwo = "Two"
let stringThree = "Three"
var array:[String] = []//If your array is string type
Type 1)
//To append elements at the end
array.append(stringOne)
array.append(stringThree)
Type 2)
//To add elements at specific index
array.insert(strigTwo, at: 1)
If you want to add two arrays
var array1 = [1,2,3,4,5]
let array2 = [6,7,8,9]
let array3 = array1+array2
print(array3)
array1.append(contentsOf: array2)
print(array1)
Use Deque instead of Array
The main benefit of Deque over Array is that it supports efficient insertions and removals at both ends.
https://swift.org/blog/swift-collections/
var names:Deque = ["Steve", "Bill", "Linus", "Bret"]
Add 'Tim' at the end of names
names.append("Tim")
Add 'Tim' at the begining of names
names.prepend("John")
Remove the first element of names
names.popFirst() // "John"
Remove the last element of names
names.popLast() // "Tim"
From page 143 of The Swift Programming Language:
You can add a new item to the end of an array by calling the array’s append method
Alternatively, add a new item to the end of an array with the addition assignment operator (+=)
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
To add to the solutions suggesting append, it's useful to know that this is an amortised constant time operation in many cases:
Complexity: Amortized O(1) unless self's storage is shared with another live array; O(count) if self does not wrap a bridged NSArray; otherwise the efficiency is unspecified.
I'm looking for a cons like operator for Swift. It should return a new immutable array with the element tacked on the end, in constant time, without changing the original array. I've not yet found a standard function that does this. I'll try to remember to report back if I find one!
You could use
Myarray.insert("Data #\(index)", atIndex: index)
If you want to append unique object, you can expand Array struct
extension Array where Element: Equatable {
mutating func appendUniqueObject(object: Generator.Element) {
if contains(object) == false {
append(object)
}
}
}
If the array is NSArray you can use the adding function to add any object at the end of the array, like this:
Swift 4.2
var myArray: NSArray = []
let firstElement: String = "First element"
let secondElement: String = "Second element"
// Process to add the elements to the array
myArray.adding(firstElement)
myArray.adding(secondElement)
Result:
print(myArray)
// ["First element", "Second element"]
That is a very simple way, regards!
In Swift 4.2:
You can use
myArray.append("Tim") //To add "Tim" into array
or
myArray.insert("Tim", at: 0) //Change 0 with specific location
Example: students = ["Ben" , "Ivy" , "Jordell"]
1) To add single elements to the end of an array, use the append(_:)
students.append(\ "Maxime" )
2) Add multiple elements at the same time by passing another array or a sequence of any kind to the append(contentsOf:) method
students.append(contentsOf: ["Shakia" , "William"])
3) To add new elements in the middle of an array by using the insert(_:at:) method for single elements
students.insert("Liam" , at:2 )
4) Using insert(contentsOf:at:) to insert multiple elements from another collection or array literal
students.insert(['Tim','TIM' at: 2 )
Swift 5.3, I believe.
The normal array wasvar myArray = ["Steve", "Bill", "Linus", "Bret"]
and you want to add "Tim" to the array, then you can use myArray.insert("Tim", at=*index*)so if you want to add it at the back of the array, then you can use myArray.append("Tim", at: 3)

What's the best way to transform an Array of type Character to a String in Swift?

This question is specifically about converting an Array of type Character to a String. Converting an Array of Strings or numbers to a string is not the topic of discussion here.
In the following 2 lines, I would expect myStringFromArray to be set to "C,a,t!,🐱"
var myChars: [Character] = ["C", "a", "t", "!", "🐱"]
let myStringFromArray = myChars.joinWithSeparator(",");
However, I can't execute that code because the compiler complains about an "ambiguous reference to member joinWithSeparator".
So, two questions:
1) Apple says,
"Every instance of Swift’s Character type represents a single extended
grapheme cluster. An extended grapheme cluster is a sequence of one or
more Unicode scalars that (when combined) produce a single
human-readable character."
Which to me sounds at least homogeneous enough to think it would be reasonable to implement the joinWithSeparator method to support the Character type. So, does anyone have a good answer as to why they don't do that???
2) What's the best way to transform an Array of type Character to a String in Swift?
Note: if you don't want a separator between the characters, the solution would be:
let myStringFromArray = String(myChars)
and that would give you "Cat!🐱"
Which to me sounds at least homogeneous enough to think it would be reasonable to implement the joinWithSeparator method to support the Character type. So, does anyone have a good answer as to why they don't do that???
This may be an oversight in the design. This error occurs because there are two possible candidates for joinWithSeparator(_:). I suspect this ambiguity exists because of the way Swift can implicit interpret double quotes as either String or Character. In this context, it's ambiguous as to which to choose.
The first candidate is joinWithSeparator(_: String) -> String. It does what you're looking for.
If the separator is treated as a String, this candidate is picked, and the result would be: "C,a,t,!,🐱"
The second is joinWithSeparator<Separator : SequenceType where Separator.Generator.Element == Generator.Element.Generator.Element>(_: Separator) -> JoinSequence<Self>. It's called on a Sequence of Sequences, and given a Sequence as a seperator. The method signature is a bit of a mouthful, so lets break it down. The argument to this function is of Separator type. This Separator is constrained to be a SequenceType where the elements of the sequence (Seperator.Generator.Element) must have the same type as the elements of this sequence of sequences (Generator.Element.Generator.Element).
The point of that complex constraint is to ensure that the Sequence remains homogeneous. You can't join sequences of Int with sequences of Double, for example.
If the separator is treated as a Character, this candidate is picked, the result would be: ["C", ",", "a", ",", "t", ",", "!", ",", "🐱"]
The compiler throws an error to ensure you're aware that there's an ambiguity. Otherwise, the program might behave differently than you'd expect.
You can disambiguate this situation by this by explicitly making each Character into a String. Because String is NOT a SequenceType, the #2 candidate is no longer possible.
var myChars: [Character] = ["C", "a", "t", "!", "🐱"]
var anotherVar = myChars.map(String.init).joinWithSeparator(",")
print(anotherVar) //C,a,t,!,🐱
This answer assumes Swift 2.2.
var myChars: [Character] = ["C", "a", "t", "!", "🐱"]
var myStrings = myChars.map({String($0)})
var result = myStrings.joinWithSeparator(",")
joinWithSeparator is only available on String arrays:
extension SequenceType where Generator.Element == String {
/// Interpose the `separator` between elements of `self`, then concatenate
/// the result. For example:
///
/// ["foo", "bar", "baz"].joinWithSeparator("-|-") // "foo-|-bar-|-baz"
#warn_unused_result
public func joinWithSeparator(separator: String) -> String
}
You could create a new extension to support Characters:
extension SequenceType where Generator.Element == Character {
#warn_unused_result
public func joinWithSeparator(separator: String) -> String {
var str = ""
self.enumerate().forEach({
str.append($1)
if let arr = self as? [Character], endIndex: Int = arr.endIndex {
if $0 < endIndex - 1 {
str.append(Character(separator))
}
}
})
return str
}
}
var myChars: [Character] = ["C", "a", "t", "!", "🐱"]
let charStr = myChars.joinWithSeparator(",") // "C,a,t,!,🐱"
Related discussion on Code Review.SE.
Context: Swift3(beta)
TL;DR Goofy Solution
var myChars:[Character] = ["C", "a", "t", "!", "🐱"]
let separators = repeatElement(Character("-"), count: myChars.count)
let zipped = zip(myChars, separators).lazy.flatMap { [$0, $1] }
let joined = String(zipped.dropLast())
Exposition
OK. This drove me nuts. In part because I got caught up in the join semantics. A join method is very useful, but when you back away from it's very specific (yet common) case of string concatenation, it's doing two things at once. It's splicing other elements in with the original sequence, and then it's flattening the 2 deep array of characters (array of strings) into one single array (string).
The OPs use of single characters in an Array sent my brain elsewhere. The answers given above are the simplest way to get what was desired. Convert the single characters to single character strings and then use the join method.
If you want to consider the two pieces separately though... We start with the original input:
var input:[Character] = ["C", "a", "t", "!", "🐱"]
Before we can splice our characters with separators, we need a collection of separators. In this case, we want a pseudo collection that is the same thing repeated again and again, without having to actually make any array with that many elements:
let separators = repeatElement(Character(","), count: myChars.count)
This returns a Repeated object (which oddly enough you cannot instantiate with a regular init method).
Now we want to splice/weave the original input with the separators:
let zipped = zip(myChars, separators).lazy.flatMap { [$0, $1] }
The zip function returns a Zip2Sequence(also curiously must be instantiated via free function rather than direct object reference). By itself, when enumerated the Zip2Sequence just enumerates paired tuples of (eachSequence1, eachSequence2). The flatMap expression turns that into a single series of alternating elements from the two sequences.
For large inputs, this would create a largish intermediary sequence, just to be soon thrown away. So we insert the lazy accessor in there which lets the transform only be computed on demand as we're accessing elements from it (think iterator).
Finally, we know we can make a String from just about any sort of Character sequence. So we just pass this directly to the String creation. We add a dropLast() to avoid the last comma being added.
let joined = String(zipped.dropLast())
The valuable thing about decomposing it this way (it's definitely more lines of code, so there had better be a redeeming value), is that we gain insight into a number of tools we could use to solve problems similar, but not identical, to join. For example, say we want the trailing comma? Joined isn't the answer. Suppose we want a non constant separator? Just rework the 2nd line. Etc...

How to use split and map method?

I saw a question: Swift: Split a String into an array
And there's some code I don't understand:
let fullName = "First Last"
let fullNameArr = split(fullName.characters){$0 == " "}.map{String($0)}
fullNameArr[0] // First
fullNameArr[1] // Last
How does split() and map{} work?
You're using a syntax that won't work in Xcode7. The correct syntax should be
let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init)
Getting that out of the way let's break down that line into two pieces:
split takes
A collection of Characters representing the String's extended
grapheme clusters
-- From Xcode docs
and a closure taking a character and returning Bool - true if the character can be considered as a separator.
if this syntax is confusing try reading that:
fullNameArr = fullName.characters.split({
character in
return character == " "
})
Now, split returns an array of SubSequence objects. You want to convert them back to string to be able to print them nicely. So one way of doing it would be creating a for loop iterating over all the results of split and converting them to string, then appending to a result array, or using map method that does the same.
If you look closely at the first line, you execute map on the array and pass a closure that does something with every element of the array and writes it back.
A simple example how that works
let exampleArray = [1, 2, 3]
print(exampleArray.map {$0 * 3})
// prints [3, 6, 9]
Hope that helps!

Concatenate String in Swift

i have an array which contains strings i.e Array
i tried to concatenate string, but i got an error as "String is not identical to UInt8"
var titleString:String! = ""
for title in array {
titleString += "\(title)"
}
To concatenate all elements of a string array, you can use the reduce method:
var string = ["this", "is", "a", "string"]
let res = string.reduce("") { $0 + $1 }
The first parameter is the initial string, which is empty, and the second is a closure, which is executed for each element in the array. The closure receives 2 parameters: the value returned at the previous step (or the initial value, if it's the 1st element), and the current element value.
More info here
Addendum I forgot to explicitly answer to your question: the concatenation doesn't work because you declared the titleString as optional - just turn into a non optional variable and it will work. If you still want to use the optional, then use forced unwrapping when doing the assignment:
titleString! += "\(title)"
Addendum 2 As suggested by #MartinR, there's another simpler way to concatenate:
join("", string)
In Swift 3, this is how you join elements of a String array:
["this", "is", "a", "string"].joined(separator: "")
Although, joined(separator:) is really geared for actually putting a separator between the strings. Reduce is still more concise:
["this", "is", "a", "string"].reduce("", +)

Add an element to an array in Swift

Suppose I have an array, for example:
var myArray = ["Steve", "Bill", "Linus", "Bret"]
And later I want to push/append an element to the end of said array, to get:
["Steve", "Bill", "Linus", "Bret", "Tim"]
What method should I use?
And what about the case where I want to add an element to the front of the array? Is there a constant time unshift?
As of Swift 3 / 4 / 5, this is done as follows.
To add a new element to the end of an Array.
anArray.append("This String")
To append a different Array to the end of your Array.
anArray += ["Moar", "Strings"]
anArray.append(contentsOf: ["Moar", "Strings"])
To insert a new element into your Array.
anArray.insert("This String", at: 0)
To insert the contents of a different Array into your Array.
anArray.insert(contentsOf: ["Moar", "Strings"], at: 0)
More information can be found in the "Collection Types" chapter of "The Swift Programming Language", starting on page 110.
You can also pass in a variable and/or object if you wanted to.
var str1:String = "John"
var str2:String = "Bob"
var myArray = ["Steve", "Bill", "Linus", "Bret"]
//add to the end of the array with append
myArray.append(str1)
myArray.append(str2)
To add them to the front:
//use 'insert' instead of append
myArray.insert(str1, atIndex:0)
myArray.insert(str2, atIndex:0)
//Swift 3
myArray.insert(str1, at: 0)
myArray.insert(str2, at: 0)
As others have already stated, you can no longer use '+=' as of xCode 6.1
To add to the end, use the += operator:
myArray += ["Craig"]
myArray += ["Jony", "Eddy"]
That operator is generally equivalent to the append(contentsOf:) method. (And in really old Swift versions, could append single elements, not just other collections of the same element type.)
There's also insert(_:at:) for inserting at any index.
If, say, you'd like a convenience function for inserting at the beginning, you could add it to the Array class with an extension.
Use += and + operators :
extension Array {
}
func += <V> (inout left: [V], right: V) {
left.append(right)
}
func + <V>(left: Array<V>, right: V) -> Array<V>
{
var map = Array<V>()
for (v) in left {
map.append(v)
}
map.append(right)
return map
}
then use :
var list = [AnyObject]()
list += "hello"
list += ["hello", "world!"]
var list2 = list + "anything"
Here is a small extension if you wish to insert at the beginning of the array without loosing the item at the first position
extension Array{
mutating func appendAtBeginning(newItem : Element){
let copy = self
self = []
self.append(newItem)
self.appendContentsOf(copy)
}
}
In Swift 4.1 and Xcode 9.4.1
We can add objects to Array basically in Two ways
let stringOne = "One"
let strigTwo = "Two"
let stringThree = "Three"
var array:[String] = []//If your array is string type
Type 1)
//To append elements at the end
array.append(stringOne)
array.append(stringThree)
Type 2)
//To add elements at specific index
array.insert(strigTwo, at: 1)
If you want to add two arrays
var array1 = [1,2,3,4,5]
let array2 = [6,7,8,9]
let array3 = array1+array2
print(array3)
array1.append(contentsOf: array2)
print(array1)
Use Deque instead of Array
The main benefit of Deque over Array is that it supports efficient insertions and removals at both ends.
https://swift.org/blog/swift-collections/
var names:Deque = ["Steve", "Bill", "Linus", "Bret"]
Add 'Tim' at the end of names
names.append("Tim")
Add 'Tim' at the begining of names
names.prepend("John")
Remove the first element of names
names.popFirst() // "John"
Remove the last element of names
names.popLast() // "Tim"
From page 143 of The Swift Programming Language:
You can add a new item to the end of an array by calling the array’s append method
Alternatively, add a new item to the end of an array with the addition assignment operator (+=)
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
To add to the solutions suggesting append, it's useful to know that this is an amortised constant time operation in many cases:
Complexity: Amortized O(1) unless self's storage is shared with another live array; O(count) if self does not wrap a bridged NSArray; otherwise the efficiency is unspecified.
I'm looking for a cons like operator for Swift. It should return a new immutable array with the element tacked on the end, in constant time, without changing the original array. I've not yet found a standard function that does this. I'll try to remember to report back if I find one!
You could use
Myarray.insert("Data #\(index)", atIndex: index)
If you want to append unique object, you can expand Array struct
extension Array where Element: Equatable {
mutating func appendUniqueObject(object: Generator.Element) {
if contains(object) == false {
append(object)
}
}
}
If the array is NSArray you can use the adding function to add any object at the end of the array, like this:
Swift 4.2
var myArray: NSArray = []
let firstElement: String = "First element"
let secondElement: String = "Second element"
// Process to add the elements to the array
myArray.adding(firstElement)
myArray.adding(secondElement)
Result:
print(myArray)
// ["First element", "Second element"]
That is a very simple way, regards!
In Swift 4.2:
You can use
myArray.append("Tim") //To add "Tim" into array
or
myArray.insert("Tim", at: 0) //Change 0 with specific location
Example: students = ["Ben" , "Ivy" , "Jordell"]
1) To add single elements to the end of an array, use the append(_:)
students.append(\ "Maxime" )
2) Add multiple elements at the same time by passing another array or a sequence of any kind to the append(contentsOf:) method
students.append(contentsOf: ["Shakia" , "William"])
3) To add new elements in the middle of an array by using the insert(_:at:) method for single elements
students.insert("Liam" , at:2 )
4) Using insert(contentsOf:at:) to insert multiple elements from another collection or array literal
students.insert(['Tim','TIM' at: 2 )
Swift 5.3, I believe.
The normal array wasvar myArray = ["Steve", "Bill", "Linus", "Bret"]
and you want to add "Tim" to the array, then you can use myArray.insert("Tim", at=*index*)so if you want to add it at the back of the array, then you can use myArray.append("Tim", at: 3)

Resources