Arrays 交换特定索引处的数组值?

Arrays 交换特定索引处的数组值?,arrays,swift,cocoa,Arrays,Swift,Cocoa,我正在为基于一系列字典的图像创建异步NSURLConnections,每个字典都有自己的图像URL: var posts = [ ["url": "url0", "calledIndex": 0], ["url": "url1", "calledIndex": 1], ["url": "url2", "calledIndex": 2], ["url": "url3", "calledIndex": 3] ] 考虑到连接的异步性质(这就是我想要的,首先加载最快的图

我正在为基于一系列字典的图像创建异步
NSURLConnections
,每个字典都有自己的图像URL:

var posts = [
    ["url": "url0", "calledIndex": 0],
    ["url": "url1", "calledIndex": 1],
    ["url": "url2", "calledIndex": 2],
    ["url": "url3", "calledIndex": 3]
]
考虑到连接的异步性质(这就是我想要的,首先加载最快的图像),图像可能会以不同的顺序加载,例如:

url0
url2
url3
url1
但是,如果图像加载顺序不正确,则需要根据加载图像的时间重新组织原始
posts
数组。因此,在上面的例子中,
posts
现在应该如下所示:

var posts = [
    ["url": "url0", "calledIndex": 0],
    ["url": "url2", "calledIndex": 2],
    ["url": "url3", "calledIndex": 3],
    ["url": "url1", "calledIndex": 1]
]
Swift中是否有任何方法可以将特定索引中数组的值与不同索引中相同数组的值进行交换?我首先尝试使用
swap
功能:

// Index the images load
var loadedIndex = 0

func connectionDidFinishLoading(connection: NSURLConnection) {

    // Index of the called image in posts
    let calledIndex = posts["calledIndex"] as! Int

    // Index that the image actually loaded
    let loadedIndex = loadedIndex

    // If the indicies are the same, the image is already in the correct position
    if loadedIndex != calledIndex {

        // If they're not the same, swap them
        swap(&posts[calledIndex], &posts[loadedIndex])
    }
}
// The post that was actually loaded
let loadedPost = posts[calledIndex]

// The post at the correct index
let postAtCorrectIndex = posts[loadedIndex]

posts[calledIndex] = postAtCorrectIndex
posts[loadedIndex] = loadedPost 
然后,我尝试了类似的操作,但没有使用
交换
功能:

// Index the images load
var loadedIndex = 0

func connectionDidFinishLoading(connection: NSURLConnection) {

    // Index of the called image in posts
    let calledIndex = posts["calledIndex"] as! Int

    // Index that the image actually loaded
    let loadedIndex = loadedIndex

    // If the indicies are the same, the image is already in the correct position
    if loadedIndex != calledIndex {

        // If they're not the same, swap them
        swap(&posts[calledIndex], &posts[loadedIndex])
    }
}
// The post that was actually loaded
let loadedPost = posts[calledIndex]

// The post at the correct index
let postAtCorrectIndex = posts[loadedIndex]

posts[calledIndex] = postAtCorrectIndex
posts[loadedIndex] = loadedPost 
但是,在这两种情况下,数组值都没有正确交换。我意识到这是一个逻辑错误,但我看不出错误到底在哪里

据我所知,它第一次正确交换,但是新字典有一个不正确的
calledIndex
值,导致它交换回原来的位置

这个假设可能是完全错误的,我意识到我很难描述这种情况,但我会尽可能多地澄清


我做了一个测试用例,你可以。其代码为:

var allPosts:Array<Dictionary<String, AnyObject>> = [
    ["imageURL": "http://i.imgur.com/aLsnGqn.jpg", "postTitle":"0"],
    ["imageURL": "http://i.imgur.com/vgTXEYY.png", "postTitle":"1"],
    ["imageURL": "http://i.imgur.com/OXzDEA6.jpg", "postTitle":"2"],
    ["imageURL": "http://i.imgur.com/ilOKOx5.jpg", "postTitle":"3"],
]

var lastIndex = 0
var threshold = 4
var activeConnections = Dictionary<NSURLConnection, Dictionary<String, AnyObject?>>()

func loadBatchInForwardDirection(){
    func createConnection(i: Int){
        allPosts[i]["calledIndex"] = i
        var post = allPosts[i]
        let imageURL = NSURL(string: post["imageURL"] as! String)
        if imageURL != nil {
            let request = NSMutableURLRequest(URL: imageURL!, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 60)
            let connection = NSURLConnection(request: request, delegate: self, startImmediately: true)
            if connection != nil {
                activeConnections[connection!] = post
            }
        }
    }
    let startingIndex = lastIndex;
    for (var i = startingIndex; i < startingIndex + threshold; i++){
        createConnection(i)
        lastIndex++
    }
}

func connection(connection: NSURLConnection, didReceiveData data: NSData) {
    if activeConnections[connection] != nil {
        let dataDict = activeConnections[connection]!["data"]
        if dataDict == nil {
            activeConnections[connection]!["data"] = NSMutableData(data: data)
        } else {
            (activeConnections[connection]!["data"] as! NSMutableData).appendData(data)
        }
    }
}

var loadedIndex = 0
func connectionDidFinishLoading(connection: NSURLConnection) {
    let loadedPost = activeConnections[connection]!
    activeConnections.removeValueForKey(connection)
    let data = loadedPost["data"] as? NSData
    let calledIndex = loadedPost["calledIndex"] as! Int
    println(calledIndex)

    swap(&allPosts[calledIndex], &allPosts[loadedIndex])
    //(allPosts[calledIndex], allPosts[loadedIndex]) = (allPosts[loadedIndex], allPosts[calledIndex])

    loadedIndex++
    done(loadedIndex)
}

func done(index: Int){
    if index == 4 {
        println()
        println("Actual: ")
        println(allPosts[0]["postTitle"] as! String)
        println(allPosts[1]["postTitle"] as! String)
        println(allPosts[2]["postTitle"] as! String)
        println(allPosts[3]["postTitle"] as! String)
    }
}

func applicationDidFinishLaunching(aNotification: NSNotification) {
    loadBatchInForwardDirection()
    println("Loaded: ")
}

func applicationWillTerminate(aNotification: NSNotification) {
    // Insert code here to tear down your application
}
var allPosts:Array=[
[“imageURL”:http://i.imgur.com/aLsnGqn.jpg“,“postTitle”:“0”],
[“imageURL”:http://i.imgur.com/vgTXEYY.png“,“postTitle”:“1”],
[“imageURL”:http://i.imgur.com/OXzDEA6.jpg“,“postTitle”:“2”],
[“imageURL”:http://i.imgur.com/ilOKOx5.jpg“,“postTitle”:“3”],
]
var lastIndex=0
风险值阈值=4
var activeConnections=Dictionary()
func loadBatchInForwardDirection(){
func createConnection(i:Int){
allPosts[i][“calledIndex”]=i
var post=所有post[i]
让imageURL=NSURL(字符串:post[“imageURL”]as!string)
如果imageURL!=nil{
let request=NSMutableURLRequest(URL:imageURL!,cachePolicy:.ReloadIgnoringLocalCacheData,timeoutInterval:60)
let connection=NSURLConnection(请求:请求,委托:self,开始时间:true)
如果连接!=nil{
activeConnections[连接!]=post
}
}
}
让startingIndex=lastIndex;
对于(var i=起始指数;i<起始指数+阈值;i++){
创建连接(i)
最后索引++
}
}
func连接(连接:NSURLConnection,didReceiveData:NSData){
如果activeConnections[连接]!=nil{
让dataDict=activeConnections[connection]![“data”]
如果dataDict==nil{
activeConnections[连接]![“数据”]=NSMutableData(数据:数据)
}否则{
(activeConnections[connection]![“data”]as!NSMutableData)。追加数据(数据)
}
}
}
var loadedIndex=0
func ConnectionIDFinishLoading(连接:NSURLConnection){
让loadedPost=activeConnections[connection]!
activeConnections.removeValueForKey(连接)
将data=loadedPost[“data”]设为NSData
让calledIndex=loadedPost[“calledIndex”]作为!Int
println(称为索引)
交换(&allPosts[calledIndex],&allPosts[loadedIndex])
//(allPosts[calledIndex],allPosts[loadedIndex])=(allPosts[loadedIndex],allPosts[calledIndex])
加载索引++
完成(加载索引)
}
func done(索引:Int){
如果索引=4{
println()
println(“实际:”)
println(所有帖子[0][“postTitle”]作为!字符串)
println(allPosts[1][“postTitle”]as!String)
println(allPosts[2][“postTitle”]as!String)
println(allPosts[3][“postTitle”]as!String)
}
}
func ApplicationIDFinishLaunching(通知:NSNotification){
loadBatchInForwardDirection()
println(“已加载:)
}
func应用程序将终止(通知:NSNotification){
//在此处插入代码以删除应用程序
}
输出为:

加载: 1. 0 2. 三,

实际: 0 1. 2. 三,

然而,预期的“实际”输出应为:

1023


值得注意的是,使用元组代码会产生稍微不稳定的结果,但与实际顺序不匹配。您可以理解我取消注释该行的意思。

您可以通过元组分配:

var xs = [1,2,3]   
(xs[1], xs[2]) = (xs[2], xs[1])
但是您在使用
交换时实际遇到了什么问题?以下几点应该很好:

swap(&xs[1], &xs[2])

如果您可以将changeIndex的值类型更改为String,那么下面的代码应该可以工作

var posts = [
    ["url": "url0", "calledIndex": "0"],
    ["url": "url2", "calledIndex": "2"],
    ["url": "url3", "calledIndex": "3"],
    ["url": "url1", "calledIndex": "1"]
]

posts = sorted(posts, { (s1: [String:String], s2: [String:String]) -> Bool in
    return s1["calledIndex"] < s2["calledIndex"]
})
var posts=[
[“url”:“url0”,“calledIndex”:“0”],
[“url”:“url2”,“calledIndex”:“2”],
[“url”:“url3”,“calledIndex”:“3”],
[“url”:“url1”,“calledIndex”:“1”]
]
posts=sorted(posts,{(s1:[String:String],s2:[String:String])->Bool-in
返回s1[“calledIndex”]
您可以对calledIndex值使用排序:

var posts = [
  ["url": "url0", "calledIndex": 0],
  ["url": "url2", "calledIndex": 2],
  ["url": "url1", "calledIndex": 1],
  ["url": "url3", "calledIndex": 3]
]


var sortedPosts = sorted(posts) { ($0["calledIndex"] as! Int) < ($1["calledIndex"] as! Int)}
var posts=[
[“url”:“url0”,“calledIndex”:0],
[“url”:“url2”,“calledIndex”:2],
[“url”:“url1”,“calledIndex”:1],
[“url”:“url3”,“calledIndex”:3]
]
var sortedPosts=sorted(posts){($0[“calledIndex”]as!Int)<($1[“calledIndex”]as!Int)}

问题在于,交换值不会给您正确的顺序,因为您可能会交换已交换的值。例如,如果您以3,0,1,2的顺序接收,则您将交换:

array_before   called_index   loaded_index   array_after
0, 1, 2, 3     0              3              3, 1, 2, 0
3, 1, 2, 0     1              0              1, 3, 2, 0
1, 3, 2, 0     2              1              1, 2, 3, 0
1, 2, 3, 0     3              2              1, 2, 0, 3
因此,这将为您提供1,2,0,3,即使您收到(并正确交换)3,0,1,2


如果您希望交换工作正常,您必须跟踪所交换的内容,以便知道要交换到哪个索引。在获取数据时,添加到新数组可能会更容易,或者添加一个新字段来存储加载的索引,并在最后对其进行排序。

这实际上比预期的要容易得多。因为当前加载的帖子被保存在
activeCo中
protocol MutableCollection {
  /// Exchange the values at indices `i` and `j`.
  ///
  /// Has no effect when `i` and `j` are equal.
  public mutating func swapAt(_ i: Index, _ j: Index)
}