假设我正在制作一个国际象棋应用程序,其中存储的位置如下:
struct Position {
var pieces: Set<Piece>
// some other stuff
}
Piece
定义如下:
struct Piece: Hashable {
var row: Int
var column: Int
let player: Player
let type: PieceType
var hashValue: Int {
return 8 * row + column
}
}
Player
和PieceType
是简单的枚举:
enum Player {
case White, Black
}
enum PieceType {
case Queen, King, ...
}
现在,我想通过其在Piece
中的位置访问Position
。 Piece
的哈希值由其位置唯一确定,因此应该可以在恒定时间内访问Piece
。但是,Swift集合没有通过其哈希值获取其元素之一的函数。我能想到的只是
for piece in pieces {
if piece.hashValue == 25 {
// do something
}
}
......但显然,这是在线性时间内运行,而不是在恒定时间内运行。
解决此问题的一种方法是不使用集合,而是使用数组:
var pieces: [Piece?]
然后,我可以在pieces[25]
中以恒定的时间访问某个位置的作品。我觉得这不太优雅,因为这个方法存储了每个Piece
两次的位置:pieces
数组中的位置以及row
和column
的值变量
有没有办法通过哈希值(在恒定时间内)访问set元素?或者我应该只使用数组?
答案 0 :(得分:2)
由于用于计算Set
的属性可能会发生变化(因为用于计算hashValue
的属性可能会发生变化),因此通常无法在hashValue
Piece
中获取Set
元素。例如Set
移动),hashValue
不知道何时发生这种情况。如果[Position: Piece]
能够以某种方式知道,那么它可能能够将元素存储在相对于WebElement mySelectElement = driver.findElement(By.id("mySelect"));
Select dropdown= new Select(mySelectElement);
的新位置,以允许后续的常量查找。基本上,如果你将它们放在一个dropdown = new Select(driver.findElement(By.id("mySelect")));
字典中,并为每次移动添加/删除键,你将会做什么。
在这种情况下,简单的数组可能是最好的解决方案。至于阵列浪费空间,它是space–time tradeoff的经典案例。
答案 1 :(得分:1)
序言:
我如何编码:
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}]
答案 2 :(得分:1)
为了使它更优雅,我会将下标添加到Board
结构中。
struct Board {
var grid: [Piece?]
let rows: Int, columns: Int
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = [Piece?](count: rows * columns, repeatedValue: nil)
}
func isValidIndex(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Piece? {
get {
assert(isValidIndex(row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set(newValue) {
assert(isValidIndex(row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
获取/设置这样的部分:
var board = Board(rows: 8, columns: 8)
board[0, 1] = Piece(player: .White, type: .King)
board[0, 2] // nil
答案 3 :(得分:0)
我会坚持使用数组。
我觉得这不太优雅,因为这个方法存储每个Piece的位置两次:通过pieces数组中的位置以及行和列变量的值。
如果你可以通过哈希访问一个集合中的值(你不能这样做),你会遇到两次存储值相同的问题。并且数组将是访问元素的更好方式。
// array
pieces[25]
// set (not possible)
pieces.elementWithHash(25)
我实际上会将其更改为使用二维数组,因为它更具可读性。
var pieces: [[Piece?]]
pieces[3][1]
答案 4 :(得分:0)
或者你可以这样做:
$('.storage').on('change', function(e) {
//console.log(day_value + night_value);
if(e.target && $(e.target).attr('id') == 'day_percent'){
/* Write the logic for your calculation you want */
}
else
if (typeof day_value != 'undefined' && typeof night_value != 'undefined') {
total = parseInt(day_value) + parseInt(night_value);
console.log('total value: ' + total);
day_percentage = (day_value / total) * 100;
console.log('day value: ' + day_value);
night_percentage = (night_value / total) * 100;
console.log('night value: ' + night_value);
$('#day_percent').val(day_percentage);
$('#night_percent').val(night_percentage);
}
});
您正在扫描8x8棋盘。不要再担心复杂性了。