用嵌套元组对数组进行排序

时间:2018-09-21 01:11:53

标签: arrays swift sorting nested tuples

我正在创建一个包含以下要素的前5名得分排行榜:

  

玩家名称

     

完成时间(完成游戏所需的时间)

     

总移动量

     

日期戳

为此,我创建了一个带有嵌套元组的元组数组,以跟踪分钟,秒和毫秒,如下所示:

var leaderBoard: [(playerName: String, completionTime: (minutes: Int, seconds: Int, miliseconds: Int), totalMoves: Int, dateStamp: Date)] = []

游戏结束后,这些值将附加到数组中,直到总共包含5个元素。

我的麻烦是我需要按完成时间升序对数组进行排序。由于该数组中元组的复杂,嵌套性质,我似乎找不到实现此目的的有效方法。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

如果您的completionTime格式正确(seconds位于0...59中,而milliseconds位于0...999中),则可以对{{1} }:

leaderboard

之所以可行,是因为Swift可以将两个元组leaderBoard.sort { $0.completionTime < $1.completionTime } (1, 2, 3)(1, 2, 4)进行比较,并且它将比较第一项,如果它们相等,则将比较第二项,如果它们相等,它将比较第三个。因此,您可以通过简单的<比较来订购它们。即使两个元素的元素数相同,元素的数量为6个或更少,并且对应元素的类型匹配,只要标记了这些元素,此方法也可以使用。


示例:

<

输出:

var leaderBoard: [(playerName: String, completionTime: (minutes: Int, seconds: Int, milliseconds: Int), totalMoves: Int, dateStamp: Date)] = [
    (playerName: "Fred", completionTime: (minutes: 4, seconds: 10, milliseconds: 800), totalMoves: 3, dateStamp: Date()),
    (playerName: "Barney", completionTime: (minutes: 5, seconds: 10, milliseconds: 800), totalMoves: 3, dateStamp: Date()),
    (playerName: "Wilma", completionTime: (minutes: 4, seconds: 10, milliseconds: 801), totalMoves: 3, dateStamp: Date()),
    (playerName: "Bam Bam", completionTime: (minutes: 1, seconds: 10, milliseconds: 0), totalMoves: 3, dateStamp: Date()),
    (playerName: "Pebbles", completionTime: (minutes: 4, seconds: 10, milliseconds: 799), totalMoves: 3, dateStamp: Date())
]

leaderBoard.sort { $0.completionTime < $1.completionTime }
leaderBoard.forEach { print($0) }

答案 1 :(得分:0)

func recordWin() {
    let newEntry: (playerName: String, completionTime: (minutes: Int, seconds: Int, miliseconds: Int), totalMoves: Int, dateStamp: Date) = (playerName, completionTime, totalMoves, dateStamp)

    if leaderBoard.count < 5 {
        leaderBoard.append(newEntry)
    }

    else {

    }

    if leaderBoard.count > 1 {
        for _ in 0...4 {
            var currentIndex = 0

            for score in leaderBoard {
                if currentIndex > 0 {
                    if score.completionTime.minutes < leaderBoard[currentIndex - 1].completionTime.minutes {
                        leaderBoard.remove(at: currentIndex)
                        leaderBoard.insert(score, at: currentIndex - 1)
                    }

                    else if score.completionTime.minutes == leaderBoard[currentIndex - 1].completionTime.minutes {
                        if score.completionTime.seconds < leaderBoard[currentIndex - 1].completionTime.seconds {
                            leaderBoard.remove(at: currentIndex)
                            leaderBoard.insert(score, at: currentIndex - 1)
                        }

                        else if score.completionTime.seconds == leaderBoard[currentIndex - 1].completionTime.seconds {
                            if score.completionTime.miliseconds < leaderBoard[currentIndex - 1].completionTime.seconds {
                                leaderBoard.remove(at: currentIndex)
                                leaderBoard.insert(score, at: currentIndex - 1)
                            }
                        }
                    }
                }

                currentIndex += 1
            }
        }
    }

    if leaderBoard.count > 5 {
        leaderBoard.removeLast()
    }

    for score in leaderBoard {
        print(score.playerName + ": " + "Completion Time: " + "Total Moves: " + score.totalMoves.description + "Completion Time: " + score.completionTime.minutes.description + ":" + score.completionTime.seconds.description + ":" + score.completionTime.miliseconds.description + " - " + score.dateStamp.description)
    }
}

答案 2 :(得分:0)

已排序的函数可以很好地完成此工作。它需要一个闭包来比较数组中的2个项目,如果第一个小于第二个,则返回true。

您只需要编写一个闭包即可计算每个完成时间的值并进行比较。进行整数数学运算的速度更快,因此下面的代码将每个完成时间转换为整数毫秒并比较这些值:

let sortedPlayers = leaderBoard.sorted { lhs, rhs in
    let lhTime =  lhs.completionTime.minutes * 60_000 + lhs.completionTime.seconds * 1000 + 
      lhs.completionTime.miliseconds
    let rhTime =  rhs.completionTime.minutes * 60_000 + rhs.completionTime.seconds * 1000 + 
      rhs.completionTime.miliseconds
    return lhTime < rhTime
}