Module mutableseqs

Module imitates scala-like behavior of mutable sequences

Its original use case was working with largish (but still manageable, i.e. fitting into memory without partitioning) sequencies, the transformed object is destroyed, so such methods will only work with vars, but not with lets

Types

WtPair*[T] = tuple[item1: T, item2: T, weight: float]
  Source Edit
KVPair*[T, U] = tuple[key: T, value: U]
  Source Edit

Procs

proc groupBy*[T, U](input: var seq[T]; action: proc (x: T): U): seq[KVPair[U, seq[T]]]

Groups elements of a sequence according to keys that calculated from elements itself works with any types that can serve as a key for table, returns sequence of key-value pairs

We can pass named functions or pass a function to generate keys implicitly

Example:

type   rndTuple = tuple[a: int,b: string]
proc getA(x: rndTuple): int = x.a
proc getB(x: rndTuple): string = x.b
var a: seq[rndTuple] = @[(1,"a"),(2,"b"),(3,"b"),(4,"a")]
assert a.groupBy(proc(x: rndTuple): string = x.b)
  == @[
        (key: a, value: @[(a: 4, b: a), (a: 1, b: a)]),
        (key: b, value: @[(a: 3, b: b), (a: 2, b: b)])
       ]
assert a.groupBy(getB)
  == @[
       (key: a, value: @[(a: 4, b: a), (a: 1, b: a)]),
       (key: b, value: @[(a: 3, b: b), (a: 2, b: b)])
       ]

Can also be used on grouping sequences of primitive types:

var g =  @[1,2,-3,3,4,5,-5]
assert g.groupBy(proc(x: int): int = x*x ) ==
   @[
     (key: 25, value: @[-5, 5]),
     (key: 16, value: @[4]),
     (key: 9, value: @[3, -3]),
     (key: 4, value: @[2]),
     (key: 1, value: @[1])
   ]      
  Source Edit
proc keys*[T, U](x: seq[KVPair[T, U]]): seq[T]
Convenience function, works with results of transformations: returns sequence of keys generated during grouping etc
assert a.groupBy(getB).keys == @[a,b]
  Source Edit
proc values*[T, U](x: seq[KVPair[T, U]]): seq[U]
Same as keys, but returns values:
assert a.groupBy(getB).values ==
  @[
    @[(a: 4, b: a), (a: 1, b: a)],
    @[(a: 3, b: b), (a: 2, b: b)]
  ]
  Source Edit
proc groupBy*[T](input: var seq[T]; action: string): seq[KVPair[string, seq[T]]]
shorter notation for groupBy, only works for tuples, if the sequence is not made of tuples an exception is thrown, moreover the keys in result will be cast to string in case a more general construction is needed, use "long notation" with full proc call passed .. code-block:
type   rndTuple = tuple[a: int,b: string]
proc getA(x: rndTuple): int = x.a
proc getB(x: rndTuple): string = x.b
var a: seq[rndTuple] = @[(1,"a"),(2,"b"),(3,"b"),(4,"a")]
assert a.groupBy(proc(x: rndTuple): string = x.b)
  == a.groupBy("b")
  Source Edit
proc groupByReducing*[T, U, V](input: var seq[T]; action: proc (x: T): U;
                            transf: proc (x: T): V): seq[KVPair[U, seq[V]]]
Same as groupBy, but now elements that are mapped into groupes can also be transformed by second function
let c = a.groupByReducing(
  proc(x:rndTuple):string = x.b,
  proc(x:rndTuple):int = x.a
)
assert c ==
   @[
     (key: a, value: @[4, 1]),
     (key: b, value: @[3, 2])
    ]
  Source Edit
proc groupByKeeping*[T, U](input: seq[T]; action: proc (x: T): U): seq[KVPair[U, seq[T]]]
Same as groupBy, but the original sequence is not transformed (can pass immutable values to it)   Source Edit
proc flatMap*[T, U](x: var seq[T]; tr: proc (y: T): seq[U]): seq[U]
Transforms every element of sequence into sequence of elements and combines them into a flat sequence
var v = @[("a",@[1,3,4],0.0),("b",@[3,4,5],4.6)]
assert v.flatMap(proc(x: tuple[a:string,b:seq[int],c:float]): seq[int]= x[1]) ==
  @[3, 4, 5, 1, 3, 4] 
  Source Edit
proc transform*[T, U](x: var seq[T]; act: proc (y: T): U): seq[U]
Same as apply from sequtils, but can produce a sequence of different type, destroys input to save space .. code-block:
var s = @[1,2,4,5]
assert s.transform(proc(x: int): float = 1.0 / x.float) == @[1.0,0.5,0.25,0.2]
  Source Edit
proc makePairs*[T, U](x: seq[T]; tr: proc (zz: T): U; wt: proc (zz: T; yy: T): float): seq[
    WtPair[U]]
Generates weighted pairs from elements of a sequence, accoring to procedures passed returns sequence of WtPair. tr function that transforms elements (before pairing), wt calculates each pair's weight
var
  j = @[("a",1),("b",2),("c",3)]
  k = j.makePairs(
    proc(
      x: tuple[a: string,b: int]): string = x.a,
        proc(
          x: tuple[a: string, b: int],
          y: tuple[a: string, b: int]
        ): float = 1.0 / (y.b.float + x.b.float)
    )
assert k ==
  @[
    (item1: c, item2: a, weight: 0.25),
    (item1: a, item2: c, weight: 0.25),
    (item1: c, item2: b, weight: 0.2),
    (item1: b, item2: c, weight: 0.2),
    (item1: b, item2: a, weight: 0.3333333333333333),
    (item1: a, item2: b, weight: 0.3333333333333333)
  ]
  Source Edit
proc take*[T](x: var seq[T]; numIt: int): seq[T]
returns n first elements of sequence   Source Edit
proc flatten*[T, U](x: seq[KVPair[U, seq[T]]]): seq[T]
in a sense "undoing" result of groupBy"   Source Edit
proc insertSort*[T](a: var openarray[T]; cmp: proc (x, y: T): bool)
yet another sorting procedure with passed comparison function   Source Edit
proc insertSort*[T](a: var openarray[T])
simple sort for values that understand < operation   Source Edit
proc shuffle*[T](x: var seq[T]): seq[T]
shuffle part of the sequence   Source Edit
proc clone*[T](x: seq[T]): seq[T]
clone a sequence   Source Edit
proc extract*[T, U](x: seq[T]; extractor: proc (y: T): U): seq[U]
extract something from a sequence   Source Edit
proc grep*[T](x: seq[T]; f: proc (y: T): bool): seq[T]
simplified imitation of perl's grep   Source Edit
proc getMedian*[T](x: var seq[T]; cmp: proc (y, z: T): bool): T
calculate a median for an array of things based on supplied comparison function   Source Edit