swift中数组操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift中数组操作相关的知识,希望对你有一定的参考价值。

参考技术A

swift内部对于数组重新赋值的时候,这个时候不会发生copy操作,仅当操作时才会进行把原来数组的值复制到新数组中

对于数组中的元素按照某种规则进行筛选

作用是将两个序列的元素,一一对应合并生成一个新序列。一般不会单独使用,而是会和其它的方法配合使用。

自定义实现类似功能,例如找出二维数组中相邻元素(相邻元素放入数组中)
swift中的extension与OC的category有点类似,但extension比起category更加强大和灵活,不仅仅可以同时扩展某种类型或结构体的方法,也可以protocol等结合使用

一般用来对所有元素的操作,例如进行单独运算或者统一转换类型等

如果你想要对集合中的每个元素都调用一个函数的话,使用 forEach 会比较合适。但是在for each中的return 语句并不会终止循环,它做的仅仅是从闭包中返回,因此在 forEach 的实现中会开始下一个循环的迭代。

“切片和它背后的数组是使用相同的索引来引用元素的。因此,切片索引不需要从零开始”,可以使用“startIndex 和 endIndex 属性做索引计算”

Swift 5:在使用协议实现 Equatable 的结构上实现通用数组操作

【中文标题】Swift 5:在使用协议实现 Equatable 的结构上实现通用数组操作【英文标题】:Swift 5: Implement generic array operations on structs implementing Equatable with protocol 【发布时间】:2020-10-07 20:28:21 【问题描述】:

我的应用中有 2 个符合协议的简单结构,以启用一些我需要在这两种类型上应用的通用操作:

import UIKit

protocol Track 
    var url: URL  get set 


struct TrackFromMediaFile: Track 
    var url: URL


struct TrackFromAsset: Track 
    var url: URL


现在我有了这些结构的列表:

var tracks = [Track]()
tracks.append(TrackFromMediaFile(url: URL(string: "http://www.remotefile")!))
tracks.append(TrackFromAsset(url: URL(string: "local://localfile")!))

我需要在这个曲目列表中找到特定曲目的索引:

// throws: 
// Value of protocol type 'Track' cannot conform to 'Equatable'; only struct/enum/class types can conform to protocols
var track = tracks[0]
tracks.firstIndex(of: track)

我尝试遵循 https://***.com/a/46719045/319905 和 https://developer.apple.com/videos/play/wwdc2015/408/ 的方法无济于事,我无法将这些方法用于我的示例。

如何以通用方式实现轨道数组的处理?

【问题讨论】:

出于好奇,您是否期望TrackFromMediaFileTrackFromAsset 能够相互平等? (我假设它们具有您未在此处列出的属性,是吗?)如果是这样,您能否描述一下您希望如何比较它们的相等性? 我会创建一个带有枚举的通用结构来区分它们。你走错了路。你不应该有一个协议的集合。 顺便说一句,如果你真的想走这条路(我不推荐)let index = tracks.firstIndex(where: track.url == $0.url) 看起来我的问题真的没有多大意义(equatable 不属于协议) - 我只需要在数组上使用 where 运算符。 【参考方案1】:

目前还不清楚您要寻找什么样的平等。如果你想检查类型相等和值相等,你可以这样做:

tracks.firstIndex(where: 
    type(of: $0) == type(of: track) && $0.url == track.url
)

如果您只想验证 url 是否相等,您可以这样做:

tracks.firstIndex(where:  $0.url == track.url )

在 Swift 中,Equatable 意味着一个值可以与其他相同类型的值进行比较。它不适用于不同类型的值。协议不是类型,它描述类型,因此 Track 本身不能是 Equatable。

如果您要经常这样做,通常可以方便地表达“能够检查与协议的其他成员是否相等”。这不是平等的,但它肯定是你可以表达的。它看起来像这样:

protocol Track 
    var url: URL  get set 
    func isEqual(to: Track) -> Bool

对于已经 Equatable 的 Track-conforming 类型,您可以提供默认实现:

extension Track where Self: Equatable 
    func isEqual(to other: Track) -> Bool 
        guard let other = other as? Self else  return false 
        return self == other
    

并将您的一致性类型标记为 Equatable(swift 将自动创建一致性):

struct TrackFromMediaFile: Track, Equatable  ... 
struct TrackFromAsset: Track, Equatable  ... 

这样,代码就更好了:

tracks.firstIndex(where:  $0.isEqual(to: track) )

如果你经常这样做,你当然可以让它变得更好一点:

extension Collection where Element == Track 
    func firstIndex(of track: Track) 
        firstIndex(where:  $0.isEqual(to: track) )
    

这样,你就可以拥有你开始使用的语法:

tracks.firstIndex(of: track)

【讨论】:

谢谢!似乎我对协议有一个错误的理解(我刚开始使用 Swift),所以我的问题没有多大意义。您的回答为我指明了正确的方向 - 我只需要使用一些数组辅助方法,例如 where。

以上是关于swift中数组操作的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Swift 数组插入和 removeAtIndex 操作行为不一致?

Swift 5:在使用协议实现 Equatable 的结构上实现通用数组操作

在 Swift 数组上设置操作(联合、交集)?

Swift高阶函数-MapFilterReduce

Swift高阶函数-MapFilterReduce

Swift高阶函数-MapFilterReduce