用相关值映射swift枚举 [英] Mapping swift enum with associated values

查看:97
本文介绍了用相关值映射swift枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说一个具有关联值类型的枚举。在下面的示例中,两个值类型是容纳图像和URL的简单对象。

 枚举内容{
case Image(ShareableImage)
case视频(ShareableVideo)
}

现在让我们有一系列的视频和图像的案例。

 让媒体:[Content] = [*很多enum案例里面这里*] 

到目前为止,所有代码都不能以任何方式在代码库中更改,我需要与它一起工作。






这里开始我的问题:



让我们用媒体过滤数组,只能使用图像的情况

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

切换项目{
case .Image:return true
默认值:return false
}
}

下一步,我想从枚举数组到其关联值的数组

  [内容]  - > [ShareableImage]通过使用地图。 

所以我这样做

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

switch imageCase {

case .Image(let image):return image
默认值:返回这里可以做什么?
}
}

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



任何想法?

解决方案

p>您可以为 .Image nil image c>否则,在 .flatMap 操作(过滤出 nil 条目):

  / *示例* / 
枚举Foo {
case Bar(Int)
case Baz(Int)
}

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

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

/ * 2.或者,正如MartinR所答:
,因为你只是寻找一个案例,替代
'如果case let'子句可以优先于'switch':* /
let barOnlyValuesAlt:[Int] = foo。 flatMap {
if case let .Bar(val)= $ 0 {return val}
else {return nil}}

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

适用于您的用例:请注意,您不需要执行过滤来创建 imageOnlyCases 数组,因为您可以直接在媒体上应用上述数组:

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

/ * 2.'如果case让'替代,按照MartinR的建议* /
let shareableImagesAlt:[ShareableImage] = media.flatMap {
如果case let .Image(image)= $ 0 {return image }
else {return nil}}

免责声明:我无法验证您的具体用例实践,因为我无法访问 ShareableImage class / struct。



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


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.

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. 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):

/* 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:

/* 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.

(Thanks @MartinR for advice that .map{ ... }.flatMap{ ... } can be simplified to just .flatMap{ ... }).

这篇关于用相关值映射swift枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆