SwiftSequence 1.0.1

SwiftSequence 1.0.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最后发布2016年5月
SPM支持SPM

Mark Hamilton维护。



  • Donnacha Oisin Kidney

SwiftSequence

完整参考信息这里

(如果您正在寻找Swift中的数据结构,它们已被移至这里)

SwiftSequence是一个轻量级的框架,用于扩展SequenceType。它没有超出Swift标准库的要求。每个函数和方法都有严格和懒加载版本,除非另有说明。

要使紧急序列变得懒惰,可以使用lazy属性。

[1, 2, 3].lazy.hop(2)

// 1, 3

贡献

欢迎贡献!任何与序列相关、适用于Linux以及包含一个或多个测试的内容都受欢迎。

内容

ScanReduce

Reduce

func reduce
    (@noescape combine: (accumulator: Generator.Element, element: Generator.Element) throws -> Generator.Element)
    rethrows -> Generator.Element?

此函数与标准库中的reduce功能相同,只是它将self的第一个元素作为初始值。它返回一个可选值,如果self为空,则为nil。

[1, 2, 3, 4].reduce(+) == 10

Scan

返回一个数组,其中包含对self中连续元素调用combine并累加器结果的中间结果

[1, 2, 3].scan(0, combine: +)

[1, 3, 6]

此数组的最后一个元素将与调用reduce以相同参数时的结果相等。

还有类似于reduce的版本,它将序列的第一个元素作为初始值

[1, 2, 3, 4, 5].scan(+)

[3, 6, 10, 15]

如果被调用的序列是懒加载的,则此版本也按需计算。

TakeDrop

prefixWhile

此函数返回直到一个元素对于predicate返回false的所有self元素

[1, 2, 3, 4, 5, 2].prefixWhile { $0 < 4 }

[1, 2, 3]

请注意,它与filter不同:如果任何元素在第一个返回false的元素之后返回true,它们仍然不会返回。

dropWhile

prefixWhile在行为上相似,此函数会移除self中返回谓词为真的前几个元素

lazy([1, 2, 3, 4, 5, 2]).dropWhile { $0 < 4 }

4, 5, 2

breakAt

返回一个元组,第一个元素是长度为nself的前缀,第二个元素是self的剩余元素。

[1, 2, 3, 4].breakAt(3) == ([1, 2, 3], [4])

这还有一个版本,它接受一个谓词,返回一个元组,其中的第一个元素是直到返回true的第一个元素为止的self的前缀。

跳跃和切片

这允许以类似Python切片的方式对多个进行索引。例如,您可以进行非封闭切片

let array = [0, 1, 2, 3, 4, 5, 6]
array[3...] == [3, 4, 5, 6]
array[...4] == [0, 1, 2, 3, 4]
array[..<4] == [0, 1, 2, 3]

您也可以通过切片进行修改

var array = [0, 1, 2, 3, 4, 5, 6]
array[...3] = [10, 11, 12, 13]
array == [10, 11, 12, 13, 4, 5, 6]

或者,您可以在数组中跳过元素

let array = [0, 1, 2, 3, 4, 5, 6]
array[2..., by: 2] // [2, 4, 6]

插入

这些函数允许在序列中以统一间隔懒惰或积极地插入元素。

插入

此函数返回插入了元素之间的self

[1, 2, 3].interpose(10)

[1, 10, 2, 10, 3]

可以指定插入元素的时间间隔

[1, 2, 3, 4, 5].interpose(10, n: 2)

[1, 2, 10, 3, 4, 10, 5]

可以插入多个元素

[1, 2, 3].interpose([10, 20])

[1, 10, 20, 2, 10, 20, 3]

可以指定间隔

[1, 2, 3, 4, 5].interpose([10, 20], n: 2)

[1, 2, 10, 20, 3, 4, 10, 20, 5]

interdig

此函数允许您通过交替从每个序列中选择元素来组合两个序列

interdig([1, 2, 3], [10, 20, 30])

[1, 10, 2, 20, 3, 30]

可以指定间齿长度

interdig([1, 2, 3, 4, 5], [10, 20, 30, 40, 50, 60], s0Len: 2, s1Len: 3)

[1, 2, 10, 20, 30, 3, 4, 40, 50, 60, 5]

组合

这些函数返回有或没有重复的组合,懒惰或积极。这些函数的懒惰版本不保留底层序列的懒惰性,但它们按需生成组合,既不存储未来的组合也不存储过去的组合,例如

let lazySequence = [1, 2, 3].lazy

let lazyCombos = lazySequence.lazyCombinations(2)

// Here, lazySequence was evaluated, but no combinations have yet been evaluated.

var g = lazyCombos.generate()

g.next() == [1, 2]

// Here, only one combination has been evaluated, and only that combination is stored in memory

g.next() == [1, 3]

// Here, two combinations have been evaluated, but no extra combinations have been stored in memory.

组合

返回长度为n的自我不重复组合

组合按照自我顺序的词法顺序返回

[1, 2, 3].combinations(2)

[1, 2], [1, 3], [2, 3]

要使组合懒惰生成并按需生成,请使用lazyCombinations()

示例配方

extension CollectionType {
  func powerSet() -> FlatMapSeq<LazyForwardCollection<Self>, ComboSeq<[Self.Generator.Element]>> {
    var i = 0
    return lazy(self).flatMap { _ in self.lazyCombinations(++i) }
  }
}

[1, 2, 3]       // [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]
  .powerSet()

重复组合

返回自我重复长度为n的组合。

组合按照自我顺序的词法顺序返回

[1, 2, 3].combinationsWithRep(2)

[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]

要生成组合并进行按需生成,请使用lazyCombinationsWithRep()

排列

字典顺序排列

这些函数按字典顺序返回排列的self,如果self不是字典序中的第一个排列,则不会返回所有排列。(要返回所有排列,可以使用sort())。此函数可以作用于元素集合,或者如果提供了关闭,则可以作用于任何集合。从懒惰的角度来看,它与组合函数的行为相同:强制评估底层集合,但可以懒惰地生成每个新的排列。要访问懒惰版本,请使用带有前缀的这些函数版本。(例如,lexPermutations()变为lazyLexPermutations()

[1, 2, 3].lexPermutations()

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
[3, 2, 1].lexPermutations()

[[3, 2, 1]]
[1, 2, 3].lexPermutations(<)

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
[1, 2, 3].lexPermutations(>)

[[1, 2, 3]]

排列

这些函数使用了与字典序排列相同的算法,但会对自身索引进行排列。(不返回索引,只是用于排列)

[1, 2, 3].permutations()

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
lazy([3, 2, 1]).lazyPermutations()

[3, 2, 1], [3, 1, 2], [2, 3, 1], [2, 1, 3], [1, 3, 2], [1, 2, 3]

周期

这些函数返回一个自身周期。如果未指定周期数,则无限循环自身。

LazySequenceType对象上调用时,返回的序列是惰性的,否则是急切的。(然而,无限周期总是惰性的)

[1, 2, 3].cycle(2)

[1, 2, 3, 1, 2, 3]
[1, 2, 3].cycle()

1, 2, 3, 1, 2, 3, 1...

分类

这些函数可用于根据某些条件对序列的元素进行分组。

分类

func categorise<U : Hashable>(keyFunc: Generator.Element -> U) -> [U:[Generator.Element]] 

此函数将自身所有元素分类到字典中,该字典的键由keyFunc指定。

[1, 2, 3, 4, 5, 6].categorise { $0 % 2 }


[
  0: [2, 4, 6],
  1: [1, 3, 5]
]

(此函数没有惰性版本)

频率

此函数返回一个字典,其中键是自身中的元素,值是它们各自的比例。

[1, 1, 1, 2, 2, 3].freqs()

[
  1: 3,
  2: 2,
  3: 1
]

(此函数没有惰性版本)

唯一

返回没有重复的self

[1, 2, 3, 2, 2, 4, 1, 2, 5, 6].uniques()

[1, 2, 3, 4, 5, 6]

分组

由于categorise()freqs()不能有惰性版本,因此这些分组函数提供了类似的行为。它们不是基于整个序列进行分类,而是基于相邻值进行分类。

这会对相邻的相同值进行分组。

lazy([1, 2, 2, 3, 1, 1, 3, 4, 2]).group()

[1], [2, 2], [3], [1, 1], [3], [4], [2]

这根据闭包对相邻的相同值进行分组。

lazy([1, 3, 5, 20, 22, 18, 6, 7]).group { abs($0 - $1) < 5 }

[1, 3, 5], [20, 22, 18], [6, 7]

这将对返回keyFunc相同结果的相邻值进行分组。

lazy([1, 3, 5, 2, 4, 6, 6, 7, 1, 1]).groupBy { $0 % 2 }

[1, 3, 5], [2, 4, 6, 6], [7, 1, 1]

块窗口分裂

这些函数将序列分割开。

此函数返回self,分割成长度为n的不重叠数组。

[1, 2, 3, 4, 5].chunk(2)

[[1, 2], [3, 4], [5]]

窗口

此函数返回self,分割成长度为n的重叠数组。

[1, 2, 3, 4, 5].window(3)

[[1, 2, 3], [2, 3, 4], [3, 4, 5]]

枚举

这只是添加了一个名为specEnumerate()的函数,它与标准库中的enumerate()相同,只不过它返回的索引是特定于基本类型,而不是仅仅是Int。例如,这个:

"hello".characters.specEnumerate()

将返回一个包含(String.Index, Character)的序列(而不是标准库中的enumerate()返回的(Int, Character),即Int和Character元组的组合)。此函数没有急切版本(正如急切版枚举函数)。

查找

这里的方法旨在替换类似于这样的模式

[1, 2, 3, 4, 5, 6].filter { n in n > 4 }.first
[1, 2, 3, 4, 5, 6].filter { n in n % 2 == 0 }.count

在这里,filter与CollectionType属性(如firstcount)链接使用。

这些链完全无效率:它们不需要地分配和填充数组。即使使用lazy属性,实际操作也是出乎意料的。例如,下面的代码:

var i = 0

[1, 2, 3, 4, 5, 6]
  .lazy
  .filter { n in
    print(++i)
    return n > 4
}.first

将打印从一到十。

提供了firstlastcount方法,它们都接受谓词,以及indicesOflastIndexOf

还提供了一个partition方法,该方法将self分割为满足和不满足predicate的数组元组。

嵌套序列

转置

允许惰性转置和急切转置。在惰性转置时,每行都会急切地计算,但只计算该行

let transposed = lazy([
  [1, 2, 3],
  [1, 2, 3],
  [1, 2, 3]
]).transpose()

var g = transposed.generate()

g.next() == [1, 1, 1]

// Each row is an eager array, but only that row is evaluated.

g.next() == [2, 2, 2]

// It's safe to use with single-pass sequences, also, as each sequence is only evaluated once.

笛卡尔积

支持惰性和急切的笛卡尔积。

product([1, 2], [3, 4])

[[1, 3], [1, 4], [2, 3], [2, 4]]

lazyProduct([1, 2], [3, 4])

[1, 3], [1, 4], [2, 3], [2, 4]

连结

这些函数允许您将两个不同长度的序列连结起来,并指定较短的序列的填充值。如果未指定,则填充值为nil。此函数没有急切版本(没有急切的库版本)

zipWithPadding([1, 2, 3], [1, 2], pad0: 100, pad1: 900)

(1, 1), (2, 2), (3, 900)
zipWithPadding([1, 2, 3], [1, 2])

(1?, 1?), (2?, 2?), (3?, nil)