我一般对Swift和编程都不熟悉。
我正在处理一个带有二维数组的项目,以表示在其中存储自定义对象的网格:
class Grid {
var element: [[GridElement]]
}
我经常需要通过其坐标访问元素。例如:
let gridElement = grid.element[coord.x][coord.y]
但是,我还需要经常从给定的gridElement(其在2d数组中的索引)获取坐标。这导致嵌套循环似乎不是最快或最优雅的解决方案:
func getCoord(_ gridElement: GridElement) -> Coord {
for x in 0..<xSize {
for y in 0..<ySize {
if element[x][y] == gridElement { return Coord(x: x, y: y) }
}
}
return Coord(x: -1, y: -1)
}
由于我希望它在大型网格上能够正常工作,所以这看起来不是解决方案。我想念一些简单的东西吗?
我正在考虑将坐标存储在GridElement对象本身中,但这也感觉很糟糕,因为当GridElement更改位置时,我需要不断更新它。
这不仅仅是设计/体系结构问题,而不是寻找神奇的功能来解决我的问题。感觉应该建立双向参考的设计模式,但我还没有找到答案。有什么建议吗?
答案 0 :(得分:0)
我正在考虑将坐标存储在GridElement对象本身中,但是这也感觉很糟糕,因为当GridElement更改位置时,我需要不断更新它。
我认为类似的解决方案是可行的。您可以将坐标存储在另一个字典中,而不是将其存储在网格元素对象中:
private var gridElementPositionDict: [GridElement: Coord]
正如您所说,这将要求您在网格元素更改位置时不断设置gridElementPositionDict
的值。 但是,您可以使用一些封装,以便仅将它们设置在一个位置。
首先,创建elements
数组private
,然后向subscript
类添加一个带有两个参数的Grid
。下标将接受Coord
,用于访问特定位置的特定网格元素。在此下标的设置者中,您可以修改gridElementPositionDict
以设置GridElement
的新位置。
然后,您可以编写另一个方法(或下标),该方法接受返回其位置的GridPosition
。
您还可以添加诸如swapElements(at:and:)
,changeElementPositon(_:to:)
之类的方法。所有这些都与封装数据结构有关。
这里有一些代码作为示例:
class Grid<T: Hashable> {
private var elements: [[T?]]
private var elementsPositionDict: [T: Coord]
init() {
elements = [
[nil, nil, nil, nil],
[nil, nil, nil, nil],
[nil, nil, nil, nil],
[nil, nil, nil, nil],
]
elementsPositionDict = [:]
}
subscript(_ coord: Coord) -> T? {
get { return elements[coord.x][coord.y] }
set {
// this is the ONLY place you modify the dictionary
if let oldValue = elements[coord.x][coord.y] {
elementsPositionDict[oldValue] = nil
}
elements[coord.x][coord.y] = newValue
if let v = newValue {
elementsPositionDict[v] = coord
}
}
}
func coord(of element: T) -> Coord? {
return elementsPositionDict[element]
}
}
答案 1 :(得分:0)
我认为您的getCoord
函数应类似于:
func getCoord(_ gridElement: GridElement) -> Coord {
for (i, row) in element.enumerated() {
if let index = row.firstIndex(of: gridElement) {
return Coord(x: i, y: index)
}
}
return Coord(x: -1, y: -1)
}
答案 2 :(得分:-1)
由于您拥有Coord类/结构,为什么不将元素存储为Coord
和GridElement
的字典,而是避免使用2D数组以及Coord
与索引中的索引之间的映射数组。这是我的建议,如何实现Grid
类
class Grid {
private var elements: [Coord: GridElement]
init() {
elements = [:]
}
func element(at coord: Coord) -> GridElement? {
return elements[coord]
}
func coord(for gridElement: GridElement) -> Coord? {
return elements.first { item in item.value == gridElement }?.key
}
}
请注意,Coord
必须实现Hashable
,并且我将字典设为私有,因为我认为如果通过函数访问字典,这是一个更好的设计