diff options
author | narimiran <narimiran@users.noreply.github.com> | 2017-10-25 13:41:42 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-10-25 13:41:41 +0200 |
commit | 71c5c0a47f1b733a3978236ac2f3be67547f2988 (patch) | |
tree | f9c90ad4b41592e838b8aae270c62293b6e38a30 /lib | |
parent | d47fec5bccde33f84a8c5e31d70dcaae184191a5 (diff) | |
download | Nim-71c5c0a47f1b733a3978236ac2f3be67547f2988.tar.gz |
Sequtils improvements (#6574)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/collections/sequtils.nim | 438 |
1 files changed, 267 insertions, 171 deletions
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 83c52e7a9..bf01d3284 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -13,8 +13,9 @@ ## were inspired by functional programming languages. ## ## For functional style programming you may want to pass `anonymous procs -## <manual.html#procedures-anonymous-procs>`_ to procs like ``filter`` to reduce typing. -## Anonymous procs can use `the special do notation <manual.html#procedures-do-notation>`_ +## <manual.html#procedures-anonymous-procs>`_ to procs like ``filter`` to +## reduce typing. Anonymous procs can use `the special do notation +## <manual.html#procedures-do-notation>`_ ## which is more convenient in certain situations. include "system/inclrtl" @@ -43,8 +44,8 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] = result[i] = itm inc(i) -proc count*[T](list: seq[T], item: T): int = - ## Count the occurrences of the item `item` in the sequence `list`. +proc count*[T](s: openArray[T], x: T): int = + ## Returns the number of occurrences of the item `x` in the container `s`. ## ## Example: ## @@ -53,12 +54,13 @@ proc count*[T](list: seq[T], item: T): int = ## s = @[1, 2, 2, 3, 2, 4, 2] ## c = count(s, 2) ## assert c == 4 - for x in items(list): - if x == item: + for itm in items(s): + if itm == x: inc result -proc cycle*[T](list: seq[T], n: Natural): seq[T] = - ## Returns a new sequence with the items of `list` repeated `n` times. +proc cycle*[T](s: openArray[T], n: Natural): seq[T] = + ## Returns a new sequence with the items of the container `s` repeated + ## `n` times. ## ## Example: ## @@ -68,15 +70,15 @@ proc cycle*[T](list: seq[T], n: Natural): seq[T] = ## s = @[1, 2, 3] ## total = s.cycle(3) ## assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3] - result = newSeq[T](n * list.len) + result = newSeq[T](n * s.len) var o = 0 for x in 0 .. <n: - for e in list: + for e in s: result[o] = e inc o -proc repeat*[T](item: T, n: Natural): seq[T] = - ## Returns a new sequence with the item `item` repeated `n` times. +proc repeat*[T](x: T, n: Natural): seq[T] = + ## Returns a new sequence with the item `x` repeated `n` times. ## ## Example: ## @@ -87,11 +89,13 @@ proc repeat*[T](item: T, n: Natural): seq[T] = ## assert total == @[5, 5, 5] result = newSeq[T](n) for i in 0 .. <n: - result[i] = item + result[i] = x -proc deduplicate*[T](list: seq[T]): seq[T] = +proc deduplicate*[T](s: openArray[T]): seq[T] = ## Returns a new sequence without duplicates. ## + ## Example: + ## ## .. code-block:: ## let ## dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4] @@ -101,17 +105,19 @@ proc deduplicate*[T](list: seq[T]): seq[T] = ## assert unique1 == @[1, 3, 4, 2, 8] ## assert unique2 == @["a", "c", "d"] result = @[] - for itm in items(list): + for itm in items(s): if not result.contains(itm): result.add(itm) {.deprecated: [distnct: deduplicate].} -proc zip*[S, T](list1: seq[S], list2: seq[T]): seq[tuple[a: S, b: T]] = - ## Returns a new sequence with a combination of the two input sequences. +proc zip*[S, T](s1: openArray[S], s2: openArray[T]): seq[tuple[a: S, b: T]] = + ## Returns a new sequence with a combination of the two input containers. ## ## For convenience you can access the returned tuples through the named - ## fields `a` and `b`. If one sequence is shorter, the remaining items in the - ## longer sequence are discarded. Example: + ## fields `a` and `b`. If one container is shorter, the remaining items in + ## the longer container are discarded. + ## + ## Example: ## ## .. code-block:: ## let @@ -124,13 +130,13 @@ proc zip*[S, T](list1: seq[S], list2: seq[T]): seq[tuple[a: S, b: T]] = ## assert zip2 == @[(1, "one"), (2, "two"), (3, "three")] ## assert zip1[2].b == 4 ## assert zip2[2].b == "three" - var m = min(list1.len, list2.len) + var m = min(s1.len, s2.len) newSeq(result, m) - for i in 0 .. m-1: - result[i] = (list1[i], list2[i]) + for i in 0 .. <m: + result[i] = (s1[i], s2[i]) -proc distribute*[T](list: seq[T], num: Positive, spread = true): seq[seq[T]] = - ## Splits and distributes a sequence `list` into `num` sub sequences. +proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] = + ## Splits and distributes a sequence `s` into `num` sub sequences. ## ## Returns a sequence of `num` sequences. For some input values this is the ## inverse of the `concat <#concat>`_ proc. The proc will assert in debug @@ -155,9 +161,9 @@ proc distribute*[T](list: seq[T], num: Positive, spread = true): seq[seq[T]] = ## assert numbers.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] ## assert numbers.distribute(6)[0] == @[1, 2] ## assert numbers.distribute(6)[5] == @[7] - assert(not list.isNil, "`list` can't be nil") + assert(not s.isNil, "`s` can't be nil") if num < 2: - result = @[list] + result = @[s] return let num = int(num) # XXX probably only needed because of .. bug @@ -165,10 +171,10 @@ proc distribute*[T](list: seq[T], num: Positive, spread = true): seq[seq[T]] = # Create the result and calculate the stride size and the remainder if any. result = newSeq[seq[T]](num) var - stride = list.len div num + stride = s.len div num first = 0 last = 0 - extra = list.len mod num + extra = s.len mod num if extra == 0 or spread == false: # Use an algorithm which overcounts the stride and minimizes reading limits. @@ -176,8 +182,8 @@ proc distribute*[T](list: seq[T], num: Positive, spread = true): seq[seq[T]] = for i in 0 .. <num: result[i] = newSeq[T]() - for g in first .. <min(list.len, first + stride): - result[i].add(list[g]) + for g in first .. <min(s.len, first + stride): + result[i].add(s[g]) first += stride else: @@ -190,32 +196,36 @@ proc distribute*[T](list: seq[T], num: Positive, spread = true): seq[seq[T]] = result[i] = newSeq[T]() for g in first .. <last: - result[i].add(list[g]) + result[i].add(s[g]) first = last -proc map*[T, S](list: openArray[T], op: proc (x: T): S {.closure.}): +proc map*[T, S](s: openArray[T], op: proc (x: T): S {.closure.}): seq[S]{.inline.} = ## Returns a new sequence with the results of `op` applied to every item in - ## `list`. + ## the container `s`. ## ## Since the input is not modified you can use this version of ``map`` to - ## transform the type of the elements in the input sequence. Example: + ## transform the type of the elements in the input container. + ## + ## Example: ## ## .. code-block:: nim ## let ## a = @[1, 2, 3, 4] ## b = map(a, proc(x: int): string = $x) ## assert b == @["1", "2", "3", "4"] - newSeq(result, list.len) - for i in 0 .. <list.len: - result[i] = op(list[i]) + newSeq(result, s.len) + for i in 0 .. <s.len: + result[i] = op(s[i]) -proc map*[T](list: var openArray[T], op: proc (x: var T) {.closure.}) +proc map*[T](s: var openArray[T], op: proc (x: var T) {.closure.}) {.deprecated.} = - ## Applies `op` to every item in `list` modifying it directly. + ## Applies `op` to every item in `s` modifying it directly. ## ## Note that this version of ``map`` requires your input and output types to - ## be the same, since they are modified in-place. Example: + ## be the same, since they are modified in-place. + ## + ## Example: ## ## .. code-block:: nim ## var a = @["1", "2", "3", "4"] @@ -225,15 +235,16 @@ proc map*[T](list: var openArray[T], op: proc (x: var T) {.closure.}) ## echo repr(a) ## # --> ["142", "242", "342", "442"] ## **Deprecated since version 0.12.0:** Use the ``apply`` proc instead. - for i in 0 .. <list.len: op(list[i]) + for i in 0 .. <s.len: op(s[i]) -proc apply*[T](list: var seq[T], op: proc (x: var T) {.closure.}) +proc apply*[T](s: var openArray[T], op: proc (x: var T) {.closure.}) {.inline.} = - ## Applies `op` to every item in `list` modifying it directly. + ## Applies `op` to every item in `s` modifying it directly. ## ## Note that this requires your input and output types to ## be the same, since they are modified in-place. ## The parameter function takes a ``var T`` type parameter. + ## ## Example: ## ## .. code-block:: nim @@ -244,15 +255,16 @@ proc apply*[T](list: var seq[T], op: proc (x: var T) {.closure.}) ## echo repr(a) ## # --> ["142", "242", "342", "442"] ## - for i in 0 .. <list.len: op(list[i]) + for i in 0 .. <s.len: op(s[i]) -proc apply*[T](list: var seq[T], op: proc (x: T): T {.closure.}) +proc apply*[T](s: var openArray[T], op: proc (x: T): T {.closure.}) {.inline.} = - ## Applies `op` to every item in `list` modifying it directly. + ## Applies `op` to every item in `s` modifying it directly. ## ## Note that this requires your input and output types to ## be the same, since they are modified in-place. ## The parameter function takes and returns a ``T`` type variable. + ## ## Example: ## ## .. code-block:: nim @@ -263,11 +275,10 @@ proc apply*[T](list: var seq[T], op: proc (x: T): T {.closure.}) ## echo repr(a) ## # --> ["142", "242", "342", "442"] ## - for i in 0 .. <list.len: list[i] = op(list[i]) - + for i in 0 .. <s.len: s[i] = op(s[i]) -iterator filter*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): T = - ## Iterates through a sequence and yields every item that fulfills the +iterator filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): T = + ## Iterates through a container and yields every item that fulfills the ## predicate. ## ## Example: @@ -277,11 +288,11 @@ iterator filter*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): T = ## for n in filter(numbers, proc (x: int): bool = x mod 2 == 0): ## echo($n) ## # echoes 4, 8, 4 in separate lines - for i in 0 .. <list.len: - if pred(list[i]): - yield list[i] + for i in 0 .. <s.len: + if pred(s[i]): + yield s[i] -proc filter*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] +proc filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): seq[T] {.inline.} = ## Returns a new sequence with all the items that fulfilled the predicate. ## @@ -295,11 +306,11 @@ proc filter*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] ## assert f1 == @["red", "black"] ## assert f2 == @["yellow"] result = newSeq[T]() - for i in 0 .. <list.len: - if pred(list[i]): - result.add(list[i]) + for i in 0 .. <s.len: + if pred(s[i]): + result.add(s[i]) -proc keepIf*[T](list: var seq[T], pred: proc(item: T): bool {.closure.}) +proc keepIf*[T](s: var seq[T], pred: proc(x: T): bool {.closure.}) {.inline.} = ## Keeps the items in the passed sequence if they fulfilled the predicate. ## Same as the ``filter`` proc, but modifies the sequence directly. @@ -311,16 +322,16 @@ proc keepIf*[T](list: var seq[T], pred: proc(item: T): bool {.closure.}) ## keepIf(floats, proc(x: float): bool = x > 10) ## assert floats == @[13.0, 12.5, 10.1] var pos = 0 - for i in 0 .. <len(list): - if pred(list[i]): + for i in 0 .. <len(s): + if pred(s[i]): if pos != i: - shallowCopy(list[pos], list[i]) + shallowCopy(s[pos], s[i]) inc(pos) - setLen(list, pos) + setLen(s, pos) -proc delete*[T](list: var seq[T]; first, last: Natural) = - ## Deletes in `list` the items at position `first` .. `last`. This modifies - ## `list` itself, it does not return a copy. +proc delete*[T](s: var seq[T]; first, last: Natural) = + ## Deletes in `s` the items at position `first` .. `last`. This modifies + ## `s` itself, it does not return a copy. ## ## Example: ## @@ -332,12 +343,12 @@ proc delete*[T](list: var seq[T]; first, last: Natural) = var i = first var j = last+1 - var newLen = len(list)-j+i + var newLen = len(s)-j+i while i < newLen: - list[i].shallowCopy(list[j]) + s[i].shallowCopy(s[j]) inc(i) inc(j) - setLen(list, newLen) + setLen(s, newLen) proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) = ## Inserts items from `src` into `dest` at position `pos`. This modifies @@ -369,11 +380,12 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) = inc(j) -template filterIt*(list, pred: untyped): untyped = +template filterIt*(s, pred: untyped): untyped = ## Returns a new sequence with all the items that fulfilled the predicate. ## ## Unlike the `proc` version, the predicate needs to be an expression using ## the ``it`` variable for testing, like: ``filterIt("abcxyz", it == 'x')``. + ## ## Example: ## ## .. code-block:: @@ -383,8 +395,8 @@ template filterIt*(list, pred: untyped): untyped = ## notAcceptable = filterIt(temperatures, it > 50 or it < -10) ## assert acceptable == @[-2.0, 24.5, 44.31] ## assert notAcceptable == @[-272.15, 99.9, -113.44] - var result = newSeq[type(list[0])]() - for it {.inject.} in items(list): + var result = newSeq[type(s[0])]() + for it {.inject.} in items(s): if pred: result.add(it) result @@ -393,6 +405,7 @@ template keepItIf*(varSeq: seq, pred: untyped) = ## ## Unlike the `proc` version, the predicate needs to be an expression using ## the ``it`` variable for testing, like: ``keepItIf("abcxyz", it == 'x')``. + ## ## Example: ## ## .. code-block:: @@ -408,8 +421,8 @@ template keepItIf*(varSeq: seq, pred: untyped) = inc(pos) setLen(varSeq, pos) -proc all*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): bool = - ## Iterates through a sequence and checks if every item fulfills the +proc all*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool = + ## Iterates through a container and checks if every item fulfills the ## predicate. ## ## Example: @@ -418,12 +431,12 @@ proc all*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): bool = ## let numbers = @[1, 4, 5, 8, 9, 7, 4] ## assert all(numbers, proc (x: int): bool = return x < 10) == true ## assert all(numbers, proc (x: int): bool = return x < 9) == false - for i in list: + for i in s: if not pred(i): return false return true -template allIt*(list, pred: untyped): bool = +template allIt*(s, pred: untyped): bool = ## Checks if every item fulfills the predicate. ## ## Example: @@ -433,14 +446,14 @@ template allIt*(list, pred: untyped): bool = ## assert allIt(numbers, it < 10) == true ## assert allIt(numbers, it < 9) == false var result = true - for it {.inject.} in items(list): + for it {.inject.} in items(s): if not pred: result = false break result -proc any*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): bool = - ## Iterates through a sequence and checks if some item fulfills the +proc any*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool = + ## Iterates through a container and checks if some item fulfills the ## predicate. ## ## Example: @@ -449,12 +462,12 @@ proc any*[T](list: seq[T], pred: proc(item: T): bool {.closure.}): bool = ## let numbers = @[1, 4, 5, 8, 9, 7, 4] ## assert any(numbers, proc (x: int): bool = return x > 8) == true ## assert any(numbers, proc (x: int): bool = return x > 9) == false - for i in list: + for i in s: if pred(i): return true return false -template anyIt*(list, pred: untyped): bool = +template anyIt*(s, pred: untyped): bool = ## Checks if some item fulfills the predicate. ## ## Example: @@ -464,7 +477,7 @@ template anyIt*(list, pred: untyped): bool = ## assert anyIt(numbers, it > 8) == true ## assert anyIt(numbers, it > 9) == false var result = false - for it {.inject.} in items(list): + for it {.inject.} in items(s): if pred: result = true break @@ -508,7 +521,9 @@ template foldl*(sequence, operation: untyped): untyped = ## variables ``a`` and ``b`` for each step of the fold. Since this is a left ## fold, for non associative binary operations like subtraction think that ## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) - - ## 3). Example: + ## 3). + ## + ## Example: ## ## .. code-block:: ## let @@ -542,6 +557,7 @@ template foldl*(sequence, operation, first): untyped = ## The ``operation`` parameter should be an expression which uses the variables ## ``a`` and ``b`` for each step of the fold. The ``first`` parameter is the ## start value (the first ``a``) and therefor defines the type of the result. + ## ## Example: ## ## .. code-block:: @@ -570,7 +586,9 @@ template foldr*(sequence, operation: untyped): untyped = ## variables ``a`` and ``b`` for each step of the fold. Since this is a right ## fold, for non associative binary operations like subtraction think that ## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 - - ## (3))). Example: + ## (3))). + ## + ## Example: ## ## .. code-block:: ## let @@ -595,13 +613,15 @@ template foldr*(sequence, operation: untyped): untyped = result = operation result -template mapIt*(list, typ, op: untyped): untyped = +template mapIt*(s, typ, op: untyped): untyped = ## Convenience template around the ``map`` proc to reduce typing. ## ## The template injects the ``it`` variable which you can use directly in an ## expression. You also need to pass as `typ` the type of the expression, ## since the new returned sequence can have a different type than the - ## original. Example: + ## original. + ## + ## Example: ## ## .. code-block:: ## let @@ -611,16 +631,18 @@ template mapIt*(list, typ, op: untyped): untyped = ## **Deprecated since version 0.12.0:** Use the ``mapIt(seq1, op)`` ## template instead. var result: seq[typ] = @[] - for it {.inject.} in items(list): + for it {.inject.} in items(s): result.add(op) result -template mapIt*(list, op: untyped): untyped = +template mapIt*(s, op: untyped): untyped = ## Convenience template around the ``map`` proc to reduce typing. ## ## The template injects the ``it`` variable which you can use directly in an - ## expression. Example: + ## expression. + ## + ## Example: ## ## .. code-block:: ## let @@ -629,19 +651,19 @@ template mapIt*(list, op: untyped): untyped = ## assert strings == @["4", "8", "12", "16"] type outType = type(( block: - var it{.inject.}: type(items(list)); + var it{.inject.}: type(items(s)); op)) var result: seq[outType] - when compiles(list.len): - let s = list + when compiles(s.len): + let t = s var i = 0 result = newSeq[outType](s.len) - for it {.inject.} in s: + for it {.inject.} in t: result[i] = op i += 1 else: result = @[] - for it {.inject.} in list: + for it {.inject.} in s: result.add(op) result @@ -650,7 +672,9 @@ template applyIt*(varSeq, op: untyped) = ## ## The template injects the ``it`` variable which you can use directly in an ## expression. The expression has to return the same type as the sequence you - ## are mutating. Example: + ## are mutating. + ## + ## Example: ## ## .. code-block:: ## var nums = @[1, 2, 3, 4] @@ -661,9 +685,10 @@ template applyIt*(varSeq, op: untyped) = varSeq[i] = op - template newSeqWith*(len: int, init: untyped): untyped = - ## creates a new sequence, calling `init` to initialize each value. Example: + ## creates a new sequence, calling `init` to initialize each value. + ## + ## Example: ## ## .. code-block:: ## var seq2D = newSeqWith(20, newSeq[bool](10)) @@ -693,58 +718,174 @@ when isMainModule: let s1 = @[1, 2, 3, 2] s2 = @['a', 'b', 'x', 'a'] + a1 = [1, 2, 3, 2] + a2 = ['a', 'b', 'x', 'a'] r0 = count(s1, 0) r1 = count(s1, 1) r2 = count(s1, 2) r3 = count(s2, 'y') r4 = count(s2, 'x') r5 = count(s2, 'a') + ar0 = count(a1, 0) + ar1 = count(a1, 1) + ar2 = count(a1, 2) + ar3 = count(a2, 'y') + ar4 = count(a2, 'x') + ar5 = count(a2, 'a') assert r0 == 0 assert r1 == 1 assert r2 == 2 assert r3 == 0 assert r4 == 1 assert r5 == 2 + assert ar0 == 0 + assert ar1 == 1 + assert ar2 == 2 + assert ar3 == 0 + assert ar4 == 1 + assert ar5 == 2 - block: # duplicates test + block: # cycle tests + let + a = @[1, 2, 3] + b: seq[int] = @[] + c = [1, 2, 3] + + doAssert a.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3] + doAssert a.cycle(0) == @[] + #doAssert a.cycle(-1) == @[] # will not compile! + doAssert b.cycle(3) == @[] + doAssert c.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3] + doAssert c.cycle(0) == @[] + + block: # repeat tests + assert repeat(10, 5) == @[10, 10, 10, 10, 10] + assert repeat(@[1,2,3], 2) == @[@[1,2,3], @[1,2,3]] + assert repeat([1,2,3], 2) == @[[1,2,3], [1,2,3]] + + block: # deduplicates test let dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4] dup2 = @["a", "a", "c", "d", "d"] + dup3 = [1, 1, 3, 4, 2, 2, 8, 1, 4] + dup4 = ["a", "a", "c", "d", "d"] unique1 = deduplicate(dup1) unique2 = deduplicate(dup2) + unique3 = deduplicate(dup3) + unique4 = deduplicate(dup4) assert unique1 == @[1, 3, 4, 2, 8] assert unique2 == @["a", "c", "d"] + assert unique3 == @[1, 3, 4, 2, 8] + assert unique4 == @["a", "c", "d"] block: # zip test let short = @[1, 2, 3] long = @[6, 5, 4, 3, 2, 1] words = @["one", "two", "three"] + ashort = [1, 2, 3] + along = [6, 5, 4, 3, 2, 1] + awords = ["one", "two", "three"] zip1 = zip(short, long) zip2 = zip(short, words) + zip3 = zip(ashort, along) + zip4 = zip(ashort, awords) + zip5 = zip(ashort, words) assert zip1 == @[(1, 6), (2, 5), (3, 4)] assert zip2 == @[(1, "one"), (2, "two"), (3, "three")] + assert zip3 == @[(1, 6), (2, 5), (3, 4)] + assert zip4 == @[(1, "one"), (2, "two"), (3, "three")] + assert zip5 == @[(1, "one"), (2, "two"), (3, "three")] assert zip1[2].b == 4 assert zip2[2].b == "three" + assert zip3[2].b == 4 + assert zip4[2].b == "three" + assert zip5[2].b == "three" + + block: # distribute tests + let numbers = @[1, 2, 3, 4, 5, 6, 7] + doAssert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]] + doAssert numbers.distribute(6)[0] == @[1, 2] + doAssert numbers.distribute(6)[5] == @[7] + let a = @[1, 2, 3, 4, 5, 6, 7] + doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]] + doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]] + doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]] + doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]] + doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]] + doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] + doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] + doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] + doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]] + doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]] + doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]] + doAssert a.distribute(6, false) == @[ + @[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]] + doAssert a.distribute(8, false) == a.distribute(8, true) + doAssert a.distribute(90, false) == a.distribute(90, true) + var b = @[0] + for f in 1 .. 25: b.add(f) + doAssert b.distribute(5, true)[4].len == 5 + doAssert b.distribute(5, false)[4].len == 2 + + block: # map test + let + numbers = @[1, 4, 5, 8, 9, 7, 4] + anumbers = [1, 4, 5, 8, 9, 7, 4] + m1 = map(numbers, proc(x: int): int = 2*x) + m2 = map(anumbers, proc(x: int): int = 2*x) + assert m1 == @[2, 8, 10, 16, 18, 14, 8] + assert m2 == @[2, 8, 10, 16, 18, 14, 8] + + block: # apply test + var a = @["1", "2", "3", "4"] + apply(a, proc(x: var string) = x &= "42") + assert a == @["142", "242", "342", "442"] block: # filter proc test let colors = @["red", "yellow", "black"] + acolors = ["red", "yellow", "black"] f1 = filter(colors, proc(x: string): bool = x.len < 6) f2 = filter(colors) do (x: string) -> bool : x.len > 5 + f3 = filter(acolors, proc(x: string): bool = x.len < 6) + f4 = filter(acolors) do (x: string) -> bool : x.len > 5 assert f1 == @["red", "black"] assert f2 == @["yellow"] + assert f3 == @["red", "black"] + assert f4 == @["yellow"] block: # filter iterator test let numbers = @[1, 4, 5, 8, 9, 7, 4] + let anumbers = [1, 4, 5, 8, 9, 7, 4] assert toSeq(filter(numbers, proc (x: int): bool = x mod 2 == 0)) == @[4, 8, 4] + assert toSeq(filter(anumbers, proc (x: int): bool = x mod 2 == 0)) == + @[4, 8, 4] block: # keepIf test var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1] keepIf(floats, proc(x: float): bool = x > 10) assert floats == @[13.0, 12.5, 10.1] + block: # delete tests + let outcome = @[1,1,1,1,1,1,1,1] + var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1] + dest.delete(3, 8) + assert outcome == dest, """\ + Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1] + is [1,1,1,1,1,1,1,1]""" + + block: # insert tests + var dest = @[1,1,1,1,1,1,1,1] + let + src = @[2,2,2,2,2,2] + outcome = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1] + dest.insert(src, 3) + assert dest == outcome, """\ + Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1] + at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]""" + block: # filterIt test let temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44] @@ -758,37 +899,49 @@ when isMainModule: keepItIf(candidates, it.len == 3 and it[0] == 'b') assert candidates == @["bar", "baz"] - block: # any - let - numbers = @[1, 4, 5, 8, 9, 7, 4] - len0seq : seq[int] = @[] - assert any(numbers, proc (x: int): bool = return x > 8) == true - assert any(numbers, proc (x: int): bool = return x > 9) == false - assert any(len0seq, proc (x: int): bool = return true) == false - - block: # anyIt - let - numbers = @[1, 4, 5, 8, 9, 7, 4] - len0seq : seq[int] = @[] - assert anyIt(numbers, it > 8) == true - assert anyIt(numbers, it > 9) == false - assert anyIt(len0seq, true) == false - block: # all let numbers = @[1, 4, 5, 8, 9, 7, 4] + anumbers = [1, 4, 5, 8, 9, 7, 4] len0seq : seq[int] = @[] assert all(numbers, proc (x: int): bool = return x < 10) == true assert all(numbers, proc (x: int): bool = return x < 9) == false assert all(len0seq, proc (x: int): bool = return false) == true + assert all(anumbers, proc (x: int): bool = return x < 10) == true + assert all(anumbers, proc (x: int): bool = return x < 9) == false block: # allIt let numbers = @[1, 4, 5, 8, 9, 7, 4] + anumbers = [1, 4, 5, 8, 9, 7, 4] len0seq : seq[int] = @[] assert allIt(numbers, it < 10) == true assert allIt(numbers, it < 9) == false assert allIt(len0seq, false) == true + assert allIt(anumbers, it < 10) == true + assert allIt(anumbers, it < 9) == false + + block: # any + let + numbers = @[1, 4, 5, 8, 9, 7, 4] + anumbers = [1, 4, 5, 8, 9, 7, 4] + len0seq : seq[int] = @[] + assert any(numbers, proc (x: int): bool = return x > 8) == true + assert any(numbers, proc (x: int): bool = return x > 9) == false + assert any(len0seq, proc (x: int): bool = return true) == false + assert any(anumbers, proc (x: int): bool = return x > 8) == true + assert any(anumbers, proc (x: int): bool = return x > 9) == false + + block: # anyIt + let + numbers = @[1, 4, 5, 8, 9, 7, 4] + anumbers = [1, 4, 5, 8, 9, 7, 4] + len0seq : seq[int] = @[] + assert anyIt(numbers, it > 8) == true + assert anyIt(numbers, it > 9) == false + assert anyIt(len0seq, true) == false + assert anyIt(anumbers, it > 8) == true + assert anyIt(anumbers, it > 9) == false block: # toSeq test let @@ -824,56 +977,13 @@ when isMainModule: assert multiplication == 495, "Multiplication is (5*(9*(11)))" assert concatenation == "nimiscool" - block: # delete tests - let outcome = @[1,1,1,1,1,1,1,1] - var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1] - dest.delete(3, 8) - assert outcome == dest, """\ - Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1] - is [1,1,1,1,1,1,1,1]""" - - block: # insert tests - var dest = @[1,1,1,1,1,1,1,1] - let - src = @[2,2,2,2,2,2] - outcome = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1] - dest.insert(src, 3) - assert dest == outcome, """\ - Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1] - at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]""" - block: # mapIt tests var nums = @[1, 2, 3, 4] strings = nums.mapIt($(4 * it)) nums.applyIt(it * 3) assert nums[0] + nums[3] == 15 - - block: # distribute tests - let numbers = @[1, 2, 3, 4, 5, 6, 7] - doAssert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]] - doAssert numbers.distribute(6)[0] == @[1, 2] - doAssert numbers.distribute(6)[5] == @[7] - let a = @[1, 2, 3, 4, 5, 6, 7] - doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]] - doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]] - doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]] - doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]] - doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]] - doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] - doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] - doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] - doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]] - doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]] - doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]] - doAssert a.distribute(6, false) == @[ - @[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]] - doAssert a.distribute(8, false) == a.distribute(8, true) - doAssert a.distribute(90, false) == a.distribute(90, true) - var b = @[0] - for f in 1 .. 25: b.add(f) - doAssert b.distribute(5, true)[4].len == 5 - doAssert b.distribute(5, false)[4].len == 2 + assert strings[2] == "12" block: # newSeqWith tests var seq2D = newSeqWith(4, newSeq[bool](2)) @@ -882,19 +992,5 @@ when isMainModule: seq2D[0][1] = true doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]] - block: # cycle tests - let - a = @[1, 2, 3] - b: seq[int] = @[] - - doAssert a.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3] - doAssert a.cycle(0) == @[] - #doAssert a.cycle(-1) == @[] # will not compile! - doAssert b.cycle(3) == @[] - - block: # repeat tests - assert repeat(10, 5) == @[10, 10, 10, 10, 10] - assert repeat(@[1,2,3], 2) == @[@[1,2,3], @[1,2,3]] - when not defined(testing): echo "Finished doc tests" |