# sequtils

- マニュアル
- 標準ライブラリ
- 索引

検索
分類:

Although this module has `seq` in its name, it implements operations not only for seq type, but for three built-in container types under the `openArray` umbrella:

- sequences
- strings
- array

The system module defines several common functions, such as:

- `newSeq[T]` for creating new sequences of type `T`
- `@` for converting arrays and strings to sequences
- `add` for adding new elements to strings and sequences
- `&` for string and seq concatenation
- `in` (alias for `contains`) and `notin` for checking if an item is in a container

This module builds upon that, providing additional functionality in form of procs, iterators and templates inspired by functional programming languages.

For functional style programming you have different options at your disposal:

- pass anonymous proc
- import sugar module and use => macro
- use ...It templates (mapIt, filterIt, etc.)

The chaining of functions is possible thanks to the method call syntax.

    import sequtils, sugar

    # Creating a sequence from 1 to 10, multiplying each member by 2,
    # keeping only the members which are not divisible by 6.
    let
      foo = toSeq(1..10).map(x => x*2).filter(x => x mod 6 != 0)
      bar = toSeq(1..10).mapIt(it*2).filterIt(it mod 6 != 0)

    doAssert foo == bar
    echo foo                  # @[2, 4, 8, 10, 14, 16, 20]

    echo foo.any(x => x > 17) # true
    echo bar.allIt(it < 20)   # false
    echo foo.foldl(a + b)     # 74; sum of all members

    import sequtils
    from strutils import join

    let
      vowels = @"aeiou" # creates a sequence @['a', 'e', 'i', 'o', 'u']
      foo = "sequtils is an awesome module"

    echo foo.filterIt(it notin vowels).join # "sqtls s n wsm mdl"

See also:

- strutils module for common string functions
- sugar module for syntactic sugar macros
- algorithm module for common generic algorithms
- json module for a structure which allows heterogeneous members

# インポート

macros, strutils, algorithm

# プロシージャ

    proc concat[T](seqs: varargs[seq[T]]): seq[T]

  Takes several sequences' items and returns them inside a new sequence. All sequences must be of the same type.

  関連:

  - distribute proc for a reverse operation

  用例:

      let
        s1 = @[1, 2, 3]
        s2 = @[4, 5]
        s3 = @[6, 7]
        total = concat(s1, s2, s3)
      assert total == @[1, 2, 3, 4, 5, 6, 7]

  ソース 編集

    proc count[T](s: openArray[T]; x: T): int

  Returns the number of occurrences of the item `x` in the container `s`.

  用例:

      let
        a = @[1, 2, 2, 3, 2, 4, 2]
        b = "abracadabra"
      assert count(a, 2) == 4
      assert count(a, 99) == 0
      assert count(b, 'r') == 2

  ソース 編集

    proc cycle[T](s: openArray[T]; n: Natural): seq[T]

  Returns a new sequence with the items of the container `s` repeated `n` times. `n` must be a non-negative number (zero or more).

  用例:

      let
        s = @[1, 2, 3]
        total = s.cycle(3)
      assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3]

  ソース 編集

    proc repeat[T](x: T; n: Natural): seq[T]

  Returns a new sequence with the item `x` repeated `n` times. `n` must be a non-negative number (zero or more).

  用例:

      let total = repeat(5, 3)
      assert total == @[5, 5, 5]

  ソース 編集

    proc deduplicate[T](s: openArray[T]; isSorted: bool = false): seq[T]

  Returns a new sequence without duplicates.

  Setting the optional argument `isSorted` to `true` (default: false) uses a faster algorithm for deduplication.

  用例:

      let
        dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
        dup2 = @["a", "a", "c", "d", "d"]
        unique1 = deduplicate(dup1)
        unique2 = deduplicate(dup2, isSorted = true)
      assert unique1 == @[1, 3, 4, 2, 8]
      assert unique2 == @["a", "c", "d"]

  ソース 編集

    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.

  The input containers can be of different types. If one container is shorter, the remaining items in the longer container are discarded.

  For convenience you can access the returned tuples through the named fields `a` and `b`.

  用例:

      let
        short = @[1, 2, 3]
        long = @[6, 5, 4, 3, 2, 1]
        words = @["one", "two", "three"]
        letters = "abcd"
        zip1 = zip(short, long)
        zip2 = zip(short, words)
        zip3 = zip(long, letters)
      assert zip1 == @[(1, 6), (2, 5), (3, 4)]
      assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
      assert zip3 ==
          @[(a: 6, b: 'a'), (a: 5, b: 'b'), (a: 4, b: 'c'), (a: 3, b: 'd')]
      assert zip1[2].b == 4
      assert zip2[2].b == "three"

  ソース 編集

    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 proc. The input sequence `s` can be empty, which will produce `num` empty sequences.

  If `spread` is false and the length of `s` is not a multiple of `num`, the proc will max out the first sub-sequence with `1 + len(s) div num` entries, leaving the remainder of elements to the last sequence.

  On the other hand, if `spread` is true, the proc will distribute evenly the remainder of the division across all sequences, which makes the result more suited to multithreading where you are passing equal sized work units to a thread pool and want to maximize core usage.

  用例:

      let numbers = @[1, 2, 3, 4, 5, 6, 7]
      assert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
      assert numbers.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
      assert numbers.distribute(6)[0] == @[1, 2]
      assert numbers.distribute(6)[1] == @[3]

  ソース 編集

    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` proc applied to every item in the container `s`.

  Since the input is not modified you can use it to transform the type of the elements in the input container.

  関連:

  - mapIt template
  - apply proc for the in-place version

  用例:

      let
        a = @[1, 2, 3, 4]
        b = map(a, proc (x: int): string =
          $x)
      assert b == @["1", "2", "3", "4"]

  ソース 編集

    proc apply[T](s: var openArray[T]; op: proc (x: var T) {...}{.closure.}) {...}{.inline.}

  Applies `op` to every item in `s` modifying it directly.

  Note that container `s` must be declared as a `var` and it is required for your input and output types to be the same, since `s` is modified in-place. The parameter function takes a `var T` type parameter.

  関連:

  - applyIt template
  - map proc

  用例:

      var a = @["1", "2", "3", "4"]
      apply(a, proc (x: var string) =
        x &= "42")
      assert a == @["142", "242", "342", "442"]

  ソース 編集

    proc apply[T](s: var openArray[T]; op: proc (x: T): T {...}{.closure.}) {...}{.inline.}

  Applies `op` to every item in `s` modifying it directly.

  Note that container `s` must be declared as a `var` and it is required for your input and output types to be the same, since `s` is modified in-place. The parameter function takes and returns a `T` type variable.

  関連:

  - applyIt template
  - map proc

  用例:

      var a = @["1", "2", "3", "4"]
      apply(a, proc (x: string): string =
        x & "42")
      assert a == @["142", "242", "342", "442"]

  ソース 編集

    proc filter[T](s: openArray[T]; pred: proc (x: T): bool {...}{.closure.}): seq[T] {...}{.inline.}

  Returns a new sequence with all the items of `s` that fulfilled the predicate `pred` (function that returns a `bool`).

  関連:

  - filterIt template
  - filter iterator
  - keepIf proc for the in-place version

  用例:

      let
        colors = @["red", "yellow", "black"]
        f1 = filter(colors, proc (x: string): bool =
          x.len < 6)
        f2 = filter(colors, proc (x: string): bool =
          x.contains('y'))
      assert f1 == @["red", "black"]
      assert f2 == @["yellow"]

  ソース 編集

    proc keepIf[T](s: var seq[T]; pred: proc (x: T): bool {...}{.closure.}) {...}{.inline.}

  Keeps the items in the passed sequence `s` if they fulfilled the predicate `pred` (function that returns a `bool`).

  Note that `s` must be declared as a `var`.

  Similar to the filter proc, but modifies the sequence directly.

  関連:

  - keepItIf template
  - filter proc

  用例:

      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]

  ソース 編集

    proc delete[T](s: var seq[T]; first, last: Natural)

  Deletes in the items of a sequence `s` at positions `first..last` (including both ends of a range). This modifies `s` itself, it does not return a copy.

  用例:

      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

  ソース 編集

    proc insert[T](dest: var seq[T]; src: openArray[T]; pos = 0)

  Inserts items from `src` into `dest` at position `pos`. This modifies `dest` itself, it does not return a copy.

  Notice that `src` and `dest` must be of the same type.

  用例:

      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

  ソース 編集

    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.

  関連:

  - allIt template
  - any proc

  用例:

      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

  ソース 編集

    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.

  関連:

  - anyIt template
  - all proc

  用例:

      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

  ソース 編集

# イテレータ

    iterator filter[T](s: openArray[T]; pred: proc (x: T): bool {...}{.closure.}): T

  Iterates through a container `s` and yields every item that fulfills the predicate `pred` (function that returns a `bool`).

  関連:

  - fliter proc
  - filterIt template

  用例:

      let numbers = @[1, 4, 5, 8, 9, 7, 4]
      var evens = newSeq[int]()
      for n in filter(numbers, proc (x: int): bool =
        x mod 2 == 0):
        evens.add(n)
      assert evens == @[4, 8, 4]

  ソース 編集

    iterator items[T](xs: iterator (): T): T

  iterates over each element yielded by a closure iterator. This may not seem particularly useful on its own, but this allows closure iterators to be used by the the mapIt, filterIt, allIt, anyIt, etc. templates. ソース 編集

# マクロ

    macro mapLiterals(constructor, op: untyped; nested = true): untyped

  Applies `op` to each of the atomic literals like `3` or `"abc"` in the specified `constructor` AST. This can be used to map every array element to some target type:

  用例:

      let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
      doAssert x is array[4, int]

  Short notation for:

      let x = [int(0.1), int(1.2), int(2.3), int(3.4)]

  If `nested` is true (which is the default), the literals are replaced everywhere in the `constructor` AST, otherwise only the first level is considered:

      let a = mapLiterals((1.2, (2.3, 3.4), 4.8), int)
      let b = mapLiterals((1.2, (2.3, 3.4), 4.8), int, nested=false)
      assert a == (1, (2, 3), 4)
      assert b == (1, (2.3, 3.4), 4)

      let c = mapLiterals((1, (2, 3), 4, (5, 6)), `$`)
      let d = mapLiterals((1, (2, 3), 4, (5, 6)), `$`, nested=false)
      assert c == ("1", ("2", "3"), "4", ("5", "6"))
      assert d == ("1", (2, 3), "4", (5, 6))

  There are no constraints for the `constructor` AST, it works for nested tuples of arrays of sets etc.

  ソース 編集

# テンプレート

    template filterIt(s, pred: untyped): untyped

  Returns a new sequence with all the items of `s` that fulfilled the predicate `pred`.

  Unlike the filter proc and filter iterator, the predicate needs to be an expression using the `it` variable for testing, like: `filterIt("abcxyz", it == 'x')`.

  関連:

  - fliter proc
  - filter iterator

  用例:

      let
        temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.90000000000001, -113.44]
        acceptable = temperatures.filterIt(it < 50 and it > -10)
        notAcceptable = temperatures.filterIt(it > 50 or it < -10)
      assert acceptable == @[-2.0, 24.5, 44.31]
      assert notAcceptable == @[-272.15, 99.90000000000001, -113.44]

  ソース 編集

    template keepItIf(varSeq: seq; pred: untyped)

  Keeps the items in the passed sequence (must be declared as a `var`) if they fulfilled the predicate.

  Unlike the keepIf proc, the predicate needs to be an expression using the `it` variable for testing, like: `keepItIf("abcxyz", it == 'x')`.

  関連:

  - keepIf proc
  - filterIt template

  用例:

      var candidates = @["foo", "bar", "baz", "foobar"]
      candidates.keepItIf(it.len == 3 and it[0] == 'b')
      assert candidates == @["bar", "baz"]

  ソース 編集

    template allIt(s, pred: untyped): bool

  Iterates through a container and checks if every item fulfills the predicate.

  Unlike the all proc, the predicate needs to be an expression using the `it` variable for testing, like: `allIt("abba", it == 'a')`.

  関連:

  - all proc
  - anyIt template

  用例:

      let numbers = @[1, 4, 5, 8, 9, 7, 4]
      assert numbers.allIt(it < 10) == true
      assert numbers.allIt(it < 9) == false

  ソース 編集

    template anyIt(s, pred: untyped): bool

  Iterates through a container and checks if some item fulfills the predicate.

  Unlike the any proc, the predicate needs to be an expression using the `it` variable for testing, like: `anyIt("abba", it == 'a')`.

  関連:

  - any proc
  - allIt template

  用例:

      let numbers = @[1, 4, 5, 8, 9, 7, 4]
      assert numbers.anyIt(it > 8) == true
      assert numbers.anyIt(it > 9) == false

  ソース 編集

    template toSeq(iter: untyped): untyped

  Transforms any iterable (anything that can be iterated over, e.g. with a for-loop) into a sequence.

  用例:

      let
        myRange = 1 .. 5
        mySet: set[int8] = {5'i8, 3, 1}
      assert type(myRange) is HSlice[system.int, system.int]
      assert type(mySet) is set[int8]
      let
        mySeq1 = toSeq(myRange)
        mySeq2 = toSeq(mySet)
      assert mySeq1 == @[1, 2, 3, 4, 5]
      assert mySeq2 == @[1'i8, 3, 5]

  ソース 編集

    template foldl(sequence, operation: untyped): untyped

  Template to fold a sequence from left to right, returning the accumulation.

  The sequence is required to have at least a single element. Debug versions of your program will assert in this situation but release versions will happily go ahead. If the sequence has a single element it will be returned without applying `operation`.

  The `operation` parameter should be an expression which uses the 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).

  関連:

  - foldl template with a starting parameter
  - foldr template

  用例:

      let
        numbers = @[5, 9, 11]
        addition = foldl(numbers, a + b)
        subtraction = foldl(numbers, a - b)
        multiplication = foldl(numbers, a * b)
        words = @["nim", "is", "cool"]
        concatenation = foldl(words, a & b)
      assert addition == 25, "Addition is (((5)+9)+11)"
      assert subtraction == -15, "Subtraction is (((5)-9)-11)"
      assert multiplication == 495, "Multiplication is (((5)*9)*11)"
      assert concatenation == "nimiscool"

  ソース 編集

    template foldl(sequence, operation, first): untyped

  Template to fold a sequence from left to right, returning the accumulation.

  This version of `foldl` gets a starting parameter. This makes it possible to accumulate the sequence into a different type than the sequence elements.

  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.

  関連:

  - foldr template

  用例:

      let
        numbers = @[0, 8, 1, 5]
        digits = foldl(numbers, a & (chr(b + ord('0'))), "")
      assert digits == "0815"

  ソース 編集

    template foldr(sequence, operation: untyped): untyped

  Template to fold a sequence from right to left, returning the accumulation.

  The sequence is required to have at least a single element. Debug versions of your program will assert in this situation but release versions will happily go ahead. If the sequence has a single element it will be returned without applying `operation`.

  The `operation` parameter should be an expression which uses the 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))).

  関連:

  - foldl template
  - foldl template with a starting parameter

  用例:

      let
        numbers = @[5, 9, 11]
        addition = foldr(numbers, a + b)
        subtraction = foldr(numbers, a - b)
        multiplication = foldr(numbers, a * b)
        words = @["nim", "is", "cool"]
        concatenation = foldr(words, a & b)
      assert addition == 25, "Addition is (5+(9+(11)))"
      assert subtraction == 7, "Subtraction is (5-(9-(11)))"
      assert multiplication == 495, "Multiplication is (5*(9*(11)))"
      assert concatenation == "nimiscool"

  ソース 編集

    template mapIt(s: typed; op: untyped): untyped

  Returns a new sequence with the results of `op` proc applied to every item in the container `s`.

  Since the input is not modified you can use it to transform the type of the elements in the input container.

  The template injects the `it` variable which you can use directly in an expression.

  関連:

  - map proc
  - applyIt template for the in-place version

  用例:

      let
        nums = @[1, 2, 3, 4]
        strings = nums.mapIt($(4 * it))
      assert strings == @["4", "8", "12", "16"]

  ソース 編集

    template mapIt(s, typ, op: untyped): untyped {...}{.error: "Deprecated since v0.12; Use \'mapIt(seq1, op)\' - without specifying the type of the returned sequence".}

  ソース 編集

    template applyIt(varSeq, op: untyped)

  Convenience template around the mutable `apply` proc to reduce typing.

  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.

  関連:

  - apply proc
  - mapIt template

  用例:

      var nums = @[1, 2, 3, 4]
      nums.applyIt(it * 3)
      assert nums[0] + nums[3] == 15

  ソース 編集

    template newSeqWith(len: int; init: untyped): untyped

  Creates a new sequence of length `len`, calling `init` to initialize each value of the sequence.

  Useful for creating "2D" sequences - sequences containing other sequences or to populate fields of the created sequence.

  用例:

      ## Creates a sequence containing 5 bool sequences, each of length of 3.
      var seq2D = newSeqWith(5, newSeq[bool](3))
      assert seq2D.len == 5
      assert seq2D[0].len == 3
      assert seq2D[4][2] == false
      ## Creates a sequence of 20 random numbers from 1 to 10
      import
        random

      var seqRand = newSeqWith(20, rand(10))

  ソース 編集