简体   繁体   English

使用关联值映射swift枚举

[英]Mapping swift enum with associated values

Let say we have an enum with associated value types. 假设我们有一个带有相关值类型的枚举。 In the example below the two value types are simple object that hold an image and a url to share. 在下面的示例中,两个值类型是包含图像的简单对象和要共享的URL。

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

Now let's have an array of video and image cases. 现在让我们来看一系列视频和图像案例。

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

All the code above so far cannot be changed in any way in the codebase, I need to work with it. 到目前为止,上面的所有代码都无法在代码库中以任何方式进行更改,我需要使用它。


Here starts my problem: 这开始我的问题:

Let's filter the array with media to only image cases 让我们用媒体过滤数组,只对图像情况进行过滤

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

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

Next step, I want to get from array of enum to an array of their associated values 下一步,我想从枚举数组获取其关联值的数组

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

so I do this 所以我这样做

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

        switch imageCase {

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

You see, I have a problem with return type..I know that the enum cases are all .Image..and I want a simple map. 你看,我有一个返回类型的问题..我知道枚举案例都是.Image ..我想要一个简单的地图。 But the swift syntax is not helping me. 但快速的语法并没有帮助我。

Any ideas? 有任何想法吗?

You could return image for case .Image , and nil otherwise, within a .flatMap operation (to "filter" out nil entries): 你可以返回image的情况下.Image ,和nil否则,内.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]

Applied to your use case: note that you needn't perform the filtering to create the imageOnlyCases array, as you can apply the above directly on the media array: 应用于您的用例:请注意,您无需执行过滤来创建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 }}

Disclaimer: I cannot verify your specific use case in practice as I don't have access to the ShareableImage class/struct. 免责声明:我无法在实践中验证您的具体用例,因为我无权访问ShareableImage类/结构。

(Thanks @MartinR for advice that .map{ ... }.flatMap{ ... } can be simplified to just .flatMap{ ... } ). (感谢@MartinR的建议,即.map{ ... }.flatMap{ ... }可以简化为.flatMap{ ... } )。

If it is guaranteed that only the .Image case can occur then you can call fatalError() in all other cases: 如果它是保证 ,只有.Image可发生情况,那么你可以调用fatalError()在所有其他情况下:

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

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

fatalError() causes the program to terminate immediately. fatalError()导致程序立即终止。 It is only meant for situations that "cannot occur", ie to find programming errors. 它仅适用于“无法发生”的情况,即发现编程错误。

It satisfies the compiler because the function is marked as @noreturn . 它满足编译器,因为该函数标记为@noreturn

If you cannot make that guarantee then use flatMap() as suggested in the other answer. 如果你不能保证,那么使用另一个答案中建议的flatMap()

Note also that you can use if case here with a pattern instead of switch/case . 另请注意,如果使用模式而不是switch/case ,则可以使用if case switch/case

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM