我正在尝试按其变量类型过滤对象数组。节点是一个具有位置的对象,但以不同的方式定义 - 作为点,矢量或附件。这是一个代码:
let product = products[(tas as NSIndexPath).row]
在最后一行,我收到了一条消息class Joint {
var position:Position
init(_ position:Position) {
self.position = position
}
}
class Position {
var point:Point {
return Point (0,0)
}
}
class Point: Position {
//Something different
}
class Vector:Position {
//Something different
}
class Attachment : Position {
//Something different
}
let content : [Joint] = [Joint(Vector()), Joint(Vector()), Joint(Attachment()), Joint(Point()), Joint(Point()) ]
let positionTypes:[Position.Type] = [Point.self, Attachment.self, Vector.self]
let points :[Position] = content.filter{$0.position is Point}.map{$0.position as! Point}
Swift.print(points)
// OK, prints: [__lldb_expr_148.Point, __lldb_expr_148.Point]
let attachments :[Position] = content.filter{$0.position is Attachment}.map{$0.position as! Attachment}
Swift.print(attachments)
// OK, prints: [__lldb_expr_148.Attachment]
let vectors :[Position] = content.filter{$0.position is Vector}.map{$0.position as! Vector}
Swift.print(vectors)
// OK, prints: [__lldb_expr_148.Vector, __lldb_expr_148.Vector]
for positionType in positionTypes {
Swift.print (positionType, type(of:positionType))
// if the next line does not exist loop returns:
// Point Position.Type
// Attachment Position.Type
// Vector Position.Type
// This line doesn't work:
let positions:[Position] = content.filter{$0.position is positionType}.map{$0.position as! positionType}
}
。
如何让最后一行工作?
答案 0 :(得分:2)
这不是正确的方法:
let points :[Position] = content.filter{$0.position is Point}.map{$0.position as! Point}
这里正确的工具是flatMap
:
let points: [Position] = content.flatMap { $0.position as? Point }
但as?
施放并非真正必要。 .position
始终是Position
;没有必要把它投入任何东西。所以你也可以这样做:
let points: [Position] = content.map { $0.position }.filter { $0 is Point }
该模式允许您执行您在最后一步中尝试执行的操作。映射到.position
,然后过滤类型。
let positions:[Position] = content
.map { $0.position }
.filter { type(of: $0) == positionType }
}
答案 1 :(得分:0)
虽然你可以沿着这条路走下去,你考虑过使用enum
吗?因为您想要在数组中表示多种类型的数据。
e.g。
//: Playground - noun: a place where people can play
import Cocoa
protocol Position {
var point: Point { get }
}
enum PositionType {
case point
case vector
case attachment
}
enum Joint {
case point(Point)
case vector(Vector)
case attachment(Attachment)
var position: Position {
switch self {
case .point(let position):
return position
case .vector(let position):
return position
case .attachment(let position):
return position
}
}
var positionType: PositionType {
switch self {
case .point:
return .point
case .vector:
return .vector
case .attachment:
return .attachment
}
}
func isPositionType(_ positionType: PositionType) -> Bool {
return self.positionType == positionType
}
}
class Point: Position {
var point: Point { return self }
}
class Vector:Position {
var point: Point { return Point() }
}
class Attachment : Position {
var point: Point { return Point() }
}
let content: [Joint] = [.vector(Vector()), .vector(Vector()), .attachment(Attachment()), .point(Point()), .point(Point()) ]
// for-in syntax
for case .point(let point) in content {
print("Point", point)
}
for case .vector(let vector) in content {
print("Vector", vector)
}
for case .attachment(let attachment) in content {
print("Attachment", attachment)
}
// using PositionType to filter
let positionTypes: [PositionType] = [ .point, .vector, .attachment ]
for positionType in positionTypes {
let positions = content.filter { $0.isPositionType(positionType) }
}
// using filter
let points = content.filter {
$0.positionType == .point
}
let vectors = content.filter {
$0.positionType == .vector
}
let attachments = content.filter {
$0.positionType == .attachment
}