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)
If you have a collection type in Swift (like a Set<T>) then you can remove something from the set like...
var s = // some set
s.remove(someElement)
and it will mutate s and remove the someElement from it.
However, this is a mutating function.
Is there a non-mutating function that would return a new set? Like...
let smallerSet = largerSet.removing(someElement)
I could use filter but then it turns this from a O(1) into an O(n) time problem.
If there isn't one already I can write one myself. Is there a convention for the name of a non-mutating function like this?
You can use subtracting function of the Set. For that you need to put that element to be deleted in another Set.
let elementToBeDeleted = Set(arrayLiteral: 1)
var wholeSet = Set(arrayLiteral: 1,2,3)
wholeSet = wholeSet.subtracting(element)
print(wholeSet) //This would print [2,3].
Hope this what you need to get things done.
I want to create a dictionary out of an array and assign a new custom object to each of them. I'll do stuff with the objects later. How can I do this?
var cals = [1,2,3]
// I want to create out of this the following dictionary
// [1:ReminderList() object, 2:ReminderList() object, 3:ReminderList() object]
let calendarsHashedToReminders = cals.map { ($0, ReminderList()) } // Creating a tuple works!
let calendarsHashedToReminders = cals.map { $0: ReminderList() } // ERROR: "Consecutive statements on a line must be separated by ';'"
map() returns an Array so you'll either have to use reduce() or create the dictionary like this:
var calendars: [Int: ReminderList] = [:]
cals.forEach { calendars[$0] = ReminderList() }
You can also use reduce() to get a oneliner but I'm not a fan of using reduce() to create an Array or a Dictionary.
Can I merge a for-in and if-let in one statement?
for item in array {
if let f = item as? NSDictionary {
result.addObject(newFile(f))
}
}
array is made by a JSON, so I don't know if each item is a NSDictionary or not. I have to check.
I was looking for something like this:
for item as? NSDictionary in array {
// code
}
Like Python or Ruby.
#nickfalk is on the right track, but we can do better. His result unfortunately returns [AnyObject], which you can't then call newFile with (I assume). But that's ok, we can get the rest of the way pretty easily.
What you want is partial map. That is to say, you want to map some (but possibly not all) of the elements of one list to another list (from AnyObject to File, if we can). So there must be some rule for choosing, and some rule for mapping. Optional let's us combine those. Let's call the function that does that f. Then its type is:
f: T->U?
So there's some magic function that will possibly convert T to U. We want to map with that. Sounds easy:
extension Array {
func partialMap<U>(f: T->U?) -> [U] {
var result = [U]()
for x in self {
if let u = f(x) {
result.append(u)
}
}
return result
}
}
So now we've hidden all the nasty mutation and var and whatnot down deep where we don't have to look at it. We have a function that takes a mapping function from "something" to "maybe something else" and returns a list of "something elses that we could map."
Now everything is nice and immutable and reusable:
let result = array.partialMap { ($0 as? NSDictionary).map(newFile) }
Whoa there. What's that map in the middle? Well, as? returns NSDictionary?. When you map an optional, then if the optional is None, it returns None, otherwise it applies the function to the value and wraps it in Some. So this whole thing takes AnyObject and returns File? just like we wanted. One partialMap later we have our answer.
I would probably just go for something like:
let result = array.filter() { $0 is NSDictionary }
If you need result to be an NSDictionary array, you can just cast it:
let result = array.filter() { $0 is NSDictionary } as [NSDictionary]
If your goal is to reduce an NSArray to an array only containing NSDictionary filter is a very powerful tool. Create the appropriate filtering function:
func filterForNSDictionary(object: AnyObject) -> Bool{
return object.isKindOfClass(NSDictionary)
}
Then simply pass in you array and function to the filter function
let result = filter(array, filterForNSDictionary)
As #RobNapier points out my solution above will end up with a result array being of the type [AnyObject] this can of course easily be remedied:
let result = filter(array, filterForNSDictionary) as [NSDictionary]
This could be considered risky, if you force the array to be of the wrong type. as [NSString] (for instance9 would most likely blow up in your face down the line...
Rob's solution being pure awesome cleverness of course and #MattGibson delivering the perfect shorthand, while exposing me as an absolute beginner in this field.