如何在Swift数组中交换元素?

40
我有一个简单的数组,如下所示:
var cellOrder = [1,2,3,4]

我想交换元素,例如将第二个元素与第一个元素交换位置。

结果应该是:

[2,1,3,4]

我知道我们可以使用exchangeObjectAtIndexNSMutableArray,但是我想使用Swift数组。有什么方法可以在Swift [Int]数组中实现相同的功能?


6
因为您发布了一个关于swap()的问题:fatal error: swapping a location with itself is not supported with Swift 2.0,所以您应该了解swap()。请注意,无需解释或提供其他内容。 - Martin R
5个回答

68

使用swap

var cellOrder = [1,2,3,4]
swap(&cellOrder[0], &cellOrder[1])

或者,你可以将它分配为元组:

(cellOrder[0], cellOrder[1]) = (cellOrder[1], cellOrder[0])

10
在 Swift 4 中,现在是 swapAt - Rishab
1
swapAt是一个不同的函数,它接受索引而不是inout值。它也可以用来解决这个问题,但不能替代Swift 4中仍然存在的swap函数。 - Rob Napier
2
我在实现这个答案时遇到了问题。当我尝试交换值时,出现了特定的错误:“同时访问0x108e19918,但修改需要独占访问权限。”使用swap对我来说效果更好。 - Karthik Kannan
为了进一步阐述上面的人所说,Swift 4中不再执行“swap(&cellOrder [0],&cellOrder [1])”,而是执行“swapAt(0,1)”,因此现在更简单了。 @RobNapier的第二个解决方案在Swift 4中仍然适用:您仍然可以通过将其分配为元组来完成工作。 - Adam
1
@Honey 只要不是集合的任何情况。swap(&x, &y) - Rob Napier
显示剩余3条评论

51

1
这并没有提供问题的答案。如果要批评或请求作者澄清,请在他们的帖子下留言。-【来自审查】 - basvk
3
我认为它回答了这个问题——它展示了如何从数组中“交换两个元素”。这是一个有效的答案,而且也是正确的。 - Zizouz212
1
@basvk 感谢您的建议。回答这个问题,cellOrder.swapAt(0, 1)更易于理解。同时也感谢 @Zizouz212。 - hstdt
2
是的,这是适用于Swift 4.0版本的有效答案。 - Paresh Patel

8

一种选项是:

cellOrder[0...1] = [cellOrder[1], cellOrder[0]]

4

详细信息

  • Xcode版本10.3(10G8),Swift 5

基础版(不安全但快速)

不安全 - 意味着,当您尝试使用数组中错误的(超出范围)索引交换元素时,可能会捕获致命错误。

var array = [1,2,3,4]
// way 1
(array[0],array[1]) = (array[1],array[0])
// way 2
array.swapAt(2, 3)

print(array)

安全交换的解决方案

  • 安全交换尝试(检查索引)
  • 可以知道哪个索引是错误的

当您需要在循环中交换大量元素时,请不要使用此解决方案。该解决方案在交换函数中验证了(i,j)索引(添加一些额外逻辑),这将使您的代码比使用标准的arr.swapAt(i,j)更慢。它非常适用于单个交换或小数组。但是,如果您决定使用标准的arr.swapAt(i,j),则必须手动检查索引或确保索引未超出范围。

import Foundation

enum SwapError: Error {
    case wrongFirstIndex
    case wrongSecondIndex
}

extension Array {
    mutating func detailedSafeSwapAt(_ i: Int, _ j: Int) throws {
        if !(0..<count ~= i) { throw SwapError.wrongFirstIndex }
        if !(0..<count ~= j) { throw SwapError.wrongSecondIndex }
        swapAt(i, j)
    }

    @discardableResult mutating func safeSwapAt(_ i: Int, _ j: Int) -> Bool {
        do {
            try detailedSafeSwapAt(i, j)
            return true
        } catch {
            return false
        }
    }
}

安全交换的使用方法

result = arr.safeSwapAt(5, 2)

//or
if arr.safeSwapAt(5, 2) {
    //Success
} else {
    //Fail
}

//or
arr.safeSwapAt(4, 8)

//or
do {
    try arr.detailedSafeSwapAt(4, 8)
} catch let error as SwapError {
    switch error {
    case .wrongFirstIndex: print("Error 1")
    case .wrongSecondIndex: print("Error 2")
    }
}

安全交换的完整示例

var arr = [10,20,30,40,50]
print("Original array: \(arr)")

print("\nSample 1 (with returning Bool = true): ")
var result = arr.safeSwapAt(1, 2)
print("Result: " + (result ? "Success" : "Fail"))
print("Array: \(arr)")

print("\nSample 2 (with returning Bool = false):")
result = arr.safeSwapAt(5, 2)
print("Result: " + (result ? "Success" : "Fail"))
print("Array: \(arr)")

print("\nSample 3 (without returning value):")
arr.safeSwapAt(4, 8)
print("Array: \(arr)")

print("\nSample 4 (with catching error):")
do {
    try arr.detailedSafeSwapAt(4, 8)
} catch let error as SwapError {
    switch error {
    case .wrongFirstIndex: print("Error 1")
    case .wrongSecondIndex: print("Error 2")
    }
}
print("Array: \(arr)")


print("\nSample 5 (with catching error):")
do {
    try arr.detailedSafeSwapAt(7, 1)
} catch let error as SwapError {
    print(error)
}
print("Array: \(arr)")

完整的安全交换样本日志

Original array: [10, 20, 30, 40, 50]

Sample 1 (with returning Bool = true): 
Result: Success
Array: [10, 30, 20, 40, 50]

Sample 2 (with returning Bool = false):
Result: Fail
Array: [10, 30, 20, 40, 50]

Sample 3 (without returning value):
Array: [10, 30, 20, 40, 50]

Sample 4 (with catching error):
Error 2
Array: [10, 30, 20, 40, 50]

Sample 5 (with catching error):
wrongFirstIndex
Array: [10, 30, 20, 40, 50]

1
使用 swapAt 方法。
var arr = [10,20,30,40,50]
arr.swapAt(2, 3)

使用索引来交换元素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接