I have a matrix, ie array of arrays. I want to add some methods to better handle this as extension to Array
. I was thinking of writting something like this:
extension Array where Element == Array {
// my methods
}
But alas, this won't compile, since I have added recursive definition. Obviosly I can omit part where Element == Array
, but it seems like nice touch to have these methods show only when appropriate. Is there some other way this can be achieved?
EDIT: as per @Leo Dabus suggestion, I will provide some use case:
I have app that has multiple table view controllers. In each of them I have sections and rows. In order to populate them, I use two arrays: one for section names, and the other one is array of arrays of objects(or structs) -> corresponding sections and rows in index paths. So I want to write methods for manipulation array of arrays based on index path. For example:
a[indexPath] = sender
These objects vary, some are simple strings, some are more complex
Try this one:
extension Array where Element: Collection {
}
To extend an array of arrays of objects (or structs) of type YourType
, use this:
extension Array where Element == Array<YourType> {
//Your methods
}
You can try this:
// extension primarily for array of arrays
extension Collection where Element: Collection {
/// all elements (rows) are of the some length
/// - `[[1,2], [3,4]].allElementsSameLength == true`
public var allElementsSameLength: Bool {
guard !isEmpty else { return true }
return dropFirst().allSatisfy { $0.count == first!.count }
}
}
run on sample data:
// array of arrays
let data = [
["labe", "value", "type"],
["name", "joe", "String"],
["age", "8", "Int"]
]
let data2 = [
["labe", "value", "type"],
["name", "joe"],
["age", "8", "Int"]
]
let data3 = [[1,1], [3,4]]
let data4 = [[1,2,3]] // one row only
let data5 = [[Int]]() // no row
and the result is:
data.allElementsSameLength, // T
data2.allElementsSameLength, // F
data3.allElementsSameLength, // T
data4.allElementsSameLength, // T
data5.allElementsSameLength, // T
The solution is to use a Contextual Where Clause on a function, rather than a where
on the extension. In a function context you can introduce generic parameters.
Here is an example which computes the trace of a 2D matrix:
public extension Array {
func trace<T: BinaryFloatingPoint>() -> T where Element == Array<T> {
var total: T = 0
for i in 0...count {
let row = self[i]
total += row[i]
}
return total
}
}
However, if you plan to implement 2D arrays, I strongly suggest you consider using a single array of size cols * rows
and then indexing it appropriately.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.