使用关联值映射swift枚举

时间:2016-02-26 11:54:33

标签: arrays swift enums

假设我们有一个带有关联值类型的枚举。在下面的示例中,两个值类型是保存图像的简单对象和要共享的URL。

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.

所以我这样做

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

        switch imageCase {

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

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

有什么想法吗?

2 个答案:

答案 0 :(得分:12)

您可以针对案例image返回.Image,并在nil操作中返回.flatMap(以“过滤掉”nil条目):< / p>

/* 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{ ... })的建议。

答案 1 :(得分:2)

如果保证,那么只会发生.Image个案 您可以在所有其他情况下致电fatalError()

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

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

fatalError()导致程序立即终止。它是 仅适用于不能发生&#34;即找到编程的情况 错误。

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

如果您无法保证,请按照建议使用flatMap() 在另一个答案中。

另请注意,您可以在此使用if case代替模式 switch/case