2016-02-26 109 views
4

假设我们有一个枚举与关联的值类型。在下面的例子中,两个值类型是简单的对象,用于保存要共享的图像和网址。使用关联值映射swift枚举

enum Content { 
    case Image(ShareableImage) 
    case Video(ShareableVideo) 
} 

现在我们来看一个视频和图像的例子。

let media: [Content] = [*a lot of enum cases inside here*] 

以上所有代码都不能以任何方式在代码库中进行更改,我需要使用它。


这里开始我的问题:

让我们从媒体的阵列进行过滤,只图像的情况下

let imageOnlyCases: [Content] = media.filter { item -> Bool in 

     switch item { 
     case .Image: return true 
     default: return false 
     } 
    } 

下一步,我想从枚举的数组得到数组它们的相关值

[Content] -> [ShareableImage] by using map. 

所以我做了th是

let shareablemages = imageOnlyCases.map { imageCase -> ShareableImage in 

     switch imageCase { 

     case .Image(let image): return image 
     default: return WHAT TO DO HERE? 
     } 
    } 

你看,我有一个返回类型的问题..我知道枚举案例都是.Image ..我想要一个简单的地图。但迅捷的语法并没有帮助我。

任何想法?

+0

我会返回零,所以你有一个optionals相关值的数组之后,你可以将它过滤到ged摆脱nil。 – Greg

回答

10

你可以对案件.Image返回imagenil否则,.flatMap操作中(“过滤”掉nil项):

/* Example */ 
enum Foo { 
    case Bar(Int) 
    case Baz(Int) 
} 

let foo: [Foo] = [.Bar(1), .Bar(9),. Baz(3), .Bar(39), .Baz(5)] 

/* 1. using 'switch' */ 
let barOnlyValues: [Int] = foo.flatMap { 
    switch $0 { 
    case .Bar(let val): return val 
    case _: return nil 
    }} 

/* 2. alternatively, as pointed out in MartinR:s answer; 
     as you're only looking for a single case, the alternative 
     'if case let' clause could be preferred over 'switch':  */ 
let barOnlyValuesAlt: [Int] = foo.flatMap { 
    if case let .Bar(val) = $0 { return val } 
    else { return nil }}        

print(barOnlyValues) // [1, 9, 39] 

适用于你的使用情况:请注意,您不需要执行过滤创建imageOnlyCases数组,可以直接应用上述的media阵列上:

/* 1. using switch */ 
let shareableImages : [ShareableImage] = media.flatMap { 
    switch $0 { 
    case .Image(let image): return image 
    case _: return nil 
    }} 

/* 2. 'if case let' alternative, as per MartinR:s suggestion */ 
let shareableImagesAlt : [ShareableImage] = media.flatMap { 
    if case let .Image(image) = $0 { return image } 
    else { return nil }} 

声明:我不能版本因为我没有访问ShareableImage类/结构的信息,所以在实际中您可能会遇到这种情况。

(感谢@MartinR的建议,.map{ ... }.flatMap{ ... }可以简化为.flatMap{ ... })。

+0

现在你快了:) - 简单:'media.flatMap {...}'而不是单独的map()和flatMap调用。 –

+0

任何人都认为'如果情况让图像(让图像)=值{...}'看起来很奇怪吗?我只是没有得到这个语法。 Swift书只有一个例子,那就是展开可选项。 – nekonari

+0

@nekonari语言指南中的示例([patterns](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Patterns.html))的确包含了访问可选的,但这仅仅是模式匹配的一个例子,在模式匹配成功的情况下,它与绑定到相关联的值的“枚举”情况相结合。在这种情况下,'Optional '就像任何通用的'enum'一样,在'enum'的情况下在一些(或几个)关联值中使用泛型。比较w。在'enum'情况下'开关'。 – dfri

1

如果保证只能出现在.Image话,那么 可以调用所有其他情况下fatalError()

let shareableImages = imageOnlyCases.map { imageCase -> ShareableImage in 

    if case let .Image(image) = imageCase { 
     return image 
    } else { 
     fatalError("Unexpected content") 
    } 
} 

fatalError()导致程序立即终止。它是 只适用于“不能发生”的情况,即找到编程 错误。

它满足编译器,因为函数被标记为@noreturn

如果您不能做出保证,那么在其他答案中使用flatMap()作为建议 。

还请注意,您可以在此处使用if case,而使用的switch/case模式。