如何分解表达式涉及按位移操作符? Swift
问题描述:
下面的代码会产生一个错误,并且无法运行,因为表达式太“复杂”。如何分解表达式涉及按位移操作符? Swift
for row in 0...NumRows {
for column in 0...NumColumns {
let topLeft = (column > 0) && (row < NumRows)
&& level.tileAt(column: column - 1, row: row) != nil
let bottomLeft = (column > 0) && (row > 0)
&& level.tileAt(column: column - 1, row: row - 1) != nil
let topRight = (column < NumColumns) && (row < NumRows)
&& level.tileAt(column: column, row: row) != nil
let bottomRight = (column < NumColumns) && (row > 0)
&& level.tileAt(column: column, row: row - 1) != nil
let value = Int(topLeft.hashValue) | Int(topRight.hashValue) << 1 | Int(bottomLeft.hashValue) << 2 | Int(bottomRight.hashValue) << 3
if value != 0 && value != 6 && value != 9 {
let name = String(format: "Tile_%ld", value)
let tileNode = SKSpriteNode(imageNamed: name)
tileNode.size = CGSize(width: TileWidth, height: TileHeight)
var point = pointFor(column: column, row: row)
point.x -= TileWidth/2
point.y -= TileHeight/2
tileNode.position = point
tilesLayer.addChild(tileNode)
}
}
}
具体来说这一行:
let value = Int(topLeft.hashValue) | Int(topRight.hashValue) << 1 | Int(bottomLeft.hashValue) << 2 | Int(bottomRight.hashValue) << 3
的误差如下:
表达过于复杂在合理时间内解决;考虑将表达式分解成不同的子表达式
如何分解值的表达式,使得它后面的代码保持相同的答案?
答
hashValue
已经是Int
,所以Int(...)
构造函数不是 需要。这将编译在Xcode 9:
let value = topLeft.hashValue | (topRight.hashValue << 1) | (bottomLeft.hashValue << 2) | (bottomRight.hashValue << 3)
但是,这是一个坏主意!它依赖于具有特定值布尔值的哈希值:
false.hashValue == 0
true.hashValue == 1
其无处保证。 (只有保证是相同的元素具有相同的散列值。我们甚至不能假定散列 值在您的程序的不同执行中相等, 请参阅Hashable
)。
一个更好的解决办法是
let value = (topLeft ? 1 : 0) + (topRight ? 2 : 0) + (bottomLeft ? 4 : 0) + (bottomRight ? 8 : 0)
另外,使用switch语句。例如:
switch (topLeft, topRight, bottomLeft, bottomRight) {
case (false, false, false, false):
// ... all false ...
case (false, true, true, false):
// ... topRight and bottomLeft are true ...
case (true, false, false, true):
// ... topLeft and bottomRight are true ...
default:
// ... all other cases ...
}
不错的答案,特别是关于不依赖boolean的hashValue的部分 –