How to rearrange item of an array to new position in Swift?
Consider the array [1,2,3,4]
. How can I rearrange the array item to new position.
For example:
put 3 into position 4 [1,2,4,3]
put 4 in to position 1 [4,1,2,3]
put 2 into position 3 [1,3,2,4]
.
Swift 3.0+:
let element = arr.remove(at: 3)
arr.insert(element, at: 2)
and in function form:
func rearrange<T>(array: Array<T>, fromIndex: Int, toIndex: Int) -> Array<T>{
var arr = array
let element = arr.remove(at: fromIndex)
arr.insert(element, at: toIndex)
return arr
}
Swift 2.0:
This puts 3 into position 4.
let element = arr.removeAtIndex(3)
arr.insert(element, atIndex: 2)
You can even make a general function:
func rearrange<T>(array: Array<T>, fromIndex: Int, toIndex: Int) -> Array<T>{
var arr = array
let element = arr.removeAtIndex(fromIndex)
arr.insert(element, atIndex: toIndex)
return arr
}
The var
arr
is needed here, because you can't mutate the input parameter without specifying it to be in-out
. In our case however we get a pure functions with no side effects, which is a lot easier to reason with, in my opinion.
You could then call it like this:
let arr = [1,2,3,4]
rearrange(arr, fromIndex: 2, toIndex: 0) //[3,1,2,4]
All great answers! Here's a more complete Swift 5 solution with performance in mind and bonus for benchmark and GIF fans. ✌️
extension Array where Element: Equatable
{
mutating func move(_ element: Element, to newIndex: Index) {
if let oldIndex: Int = self.firstIndex(of: element) { self.move(from: oldIndex, to: newIndex) }
}
}
extension Array
{
mutating func move(from oldIndex: Index, to newIndex: Index) {
// Don't work for free and use swap when indices are next to each other - this
// won't rebuild array and will be super efficient.
if oldIndex == newIndex { return }
if abs(newIndex - oldIndex) == 1 { return self.swapAt(oldIndex, newIndex) }
self.insert(self.remove(at: oldIndex), at: newIndex)
}
}
edit/update: Swift 3.x
extension RangeReplaceableCollection where Indices: Equatable {
mutating func rearrange(from: Index, to: Index) {
precondition(from != to && indices.contains(from) && indices.contains(to), "invalid indices")
insert(remove(at: from), at: to)
}
}
var numbers = [1,2,3,4]
numbers.rearrange(from: 1, to: 2)
print(numbers) // [1, 3, 2, 4]
nice tip from Leo.
for Swift 3...5.5:
extension Array {
mutating func rearrange(from: Int, to: Int) {
insert(remove(at: from), at: to)
}
}
var myArray = [1,2,3,4]
myArray.rearrange(from: 1, to: 2)
print(myArray)