2D数组扩展Swift 3.1.1 [英] 2D Array extension Swift 3.1.1
问题描述
我正在尝试在Swift 3.1.1中进行 Array
扩展,以支持将对象添加到2D Array中的特定索引,即使未填充该数组也是如此还.该扩展还应该提供在特定 indexPath
处获取对象的功能.我在Swift 2中有此代码,但似乎无法将其迁移到Swift3.这是Swift 2代码:
I am trying to make an Array
extension in Swift 3.1.1 that supports the addition of an object to a certain index in a 2D Array even if the array hasn't been populated yet. The extension should also provide the ability to get an object at certain indexPath
. I have the code for this in Swift 2 but I don't seem to be able to migrate it to Swift 3. This is the Swift 2 code:
extension Array where Element: _ArrayProtocol, Element.Iterator.Element: Any {
mutating func addObject(_ anObject : Element.Iterator.Element, toSubarrayAtIndex idx : Int) {
while self.count <= idx {
let newSubArray = Element()
self.append(newSubArray)
}
var subArray = self[idx]
subArray.append(anObject)
}
func objectAtIndexPath(_ indexPath: IndexPath) -> Any {
let subArray = self[indexPath.section]
return subArray[indexPath.row] as Element.Iterator.Element
}
}
此代码来自此 answer .
推荐答案
正如马丁在此处的回答中所述 ,<代码> _ArrayProtocol 在Swift 3.1中不再是 public
,因此,您不能将其用作扩展中的约束.
As Martin says in his answer here, _ArrayProtocol
is no longer public
in Swift 3.1, therefore meaning that you cannot use it as a constraint in your extension.
在您的情况下,一个简单的替代方法是将 Array
的 Element
约束为 append(_:)方法,以便将元素添加到集合中.
A simple alternative in your case is to instead constrain the Array
's Element
to being a RangeReplaceableCollection
– which both defines an init()
requirement meaning "empty collection", and an append(_:)
method in order to add elements to the collection.
extension Array where Element : RangeReplaceableCollection {
typealias InnerCollection = Element
typealias InnerElement = InnerCollection.Iterator.Element
mutating func fillingAppend(
_ newElement: InnerElement,
toSubCollectionAtIndex index: Index) {
if index >= count {
append(contentsOf: repeatElement(InnerCollection(), count: index + 1 - count))
}
self[index].append(newElement)
}
}
还请注意,我们将添加作为单个调用进行(使用 append(contentsOf:
)),以确保我们最多只需要调整外部数组的大小.
Note also that we're doing the append as a single call (using append(contentsOf:
), ensuring that we only have to resize the outer array at most once.
要使您的方法从给定的 IndexPath
中获取元素,只需将内部元素类型限制为
For your method to get an element from a given IndexPath
, you can just constrain the inner element type to being a Collection
with an Int
Index
:
// could also make this an extension on Collection where the outer Index is also an Int.
extension Array where Element : Collection, Element.Index == Int {
subscript(indexPath indexPath: IndexPath) -> Element.Iterator.Element {
return self[indexPath.section][indexPath.row]
}
}
请注意,我将其设为 subscript
而不是方法,因为我觉得它更适合 Array
的API.
Note that I've made it a subscript
rather than a method, as I feel it fits better with Array
's API.
您现在可以像这样简单地使用这些扩展名:
You can now simply use these extensions like so:
var arr = [[Int]]()
arr.fillingAppend(6, toSubCollectionAtIndex: 3)
print(arr) // [[], [], [], [6]]
let indexPath = IndexPath(row: 0, section: 3)
print(arr[indexPath: indexPath]) // 6
当然,如果您事先知道外部数组的大小,则 fillingAppend(_:toSubCollectionAtIndex:)
方法是多余的,因为您可以这样说来创建嵌套数组:>
Although of course if you know the size of the outer array in advance, the fillingAppend(_:toSubCollectionAtIndex:)
method is redundant, as you can just create your nested array by saying:
var arr = [[Int]](repeating: [], count: 5)
这将创建一个 [[Int]]
数组,其中包含5个空的 [Int]
元素.
which will create an [[Int]]
array containing 5 empty [Int]
elements.
这篇关于2D数组扩展Swift 3.1.1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!