通过哈希值访问 Swift 集合元素

Tim*_*len 5 hash set swift

假设我正在制作一个国际象棋应用程序,其中的位置存储如下:

struct Position {
    var pieces: Set<Piece>
    // some other stuff
}
Run Code Online (Sandbox Code Playgroud)

Piece 定义如下:

struct Piece: Hashable {
    var row: Int
    var column: Int
    let player: Player
    let type: PieceType

    var hashValue: Int {
        return 8 * row + column
    }
}
Run Code Online (Sandbox Code Playgroud)

Player并且PieceType是简单的枚举:

enum Player {
    case White, Black
}

enum PieceType {
    case Queen, King, ...
}
Run Code Online (Sandbox Code Playgroud)

现在,我想通过 a Piecein aPosition在董事会上的位置来访问它。a 的哈希值Piece由其位置唯一确定,因此Piece应该可以在恒定时间内访问 a 。但是,Swift 集合没有通过其哈希值获取其元素之一的函数。我能想到的就是

for piece in pieces {
    if piece.hashValue == 25 {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

...但显然,这在线性时间内运行,而不是在恒定时间内。

解决这个问题的一种方法是不使用集合,而是使用数组:

var pieces: [Piece?]
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地使用pieces[25], 在恒定时间内访问某个位置的作品。我确实觉得这不太优雅,因为这种方法将每个的位置存储Piece两次:通过pieces数组中的位置和rowcolumn变量的值。

有没有办法通过散列值(在恒定时间内)访问集合元素?或者我应该只使用一个数组?

How*_*att 1

前言:

  1. 由于有 64 个方格,最好有一组可选的棋子
  2. 通常,您使用带有 Int 键的字典作为稀疏数组(请参见下面的示例)
  3. 您不应该单独使用 hashValue 作为位置,因为它应该考虑所有属性(我在下面的示例中更改为位置) - 尽管我在这种情况下得到了这一点,但暂时没有 2 个部分可以具有相同的位置,因此可能没问题

我如何编码:

struct Piece {
    var row: Int
    var column: Int
    let player: Player
    let type: PieceType

    var location: Int {
        return 8 * row + column
    }
}

struct Board {
    var pieces = [Int : Piece]()

    init(pieces: Piece...) {
        pieces.forEach {
            self.pieces[$0.location] = $0
        }
    }
}

let whiteKing = Piece(row: 0, column: 4, player: .White, type: .King)
let blackKing = Piece(row: 7, column: 3, player: .Black, type: .King)

let board = Board(pieces: whiteKing, blackKing)

board.pieces // [4: {row 0, column 4, White, King}, 59: {row 7, column 3, Black, King}]
Run Code Online (Sandbox Code Playgroud)