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
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