From 73b0bb52bbeb24d2a5abfa80332be376e27e791c Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sun, 23 Oct 2016 11:21:52 +0200 Subject: Table fixes. fixes #4901 * added `==` for OrderedTable, CountTable and the *Ref types * added missing documentation to all `==` procs * fixed clear() for OrderedTables, which did not work because `var` does not work well with `|` * added tests --- lib/pure/collections/tables.nim | 41 +++++++++++++++++++++++++++++++++++++---- tests/collections/ttables.nim | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 778ea5ca3..fe75f9a58 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -338,7 +338,7 @@ proc hasKey*[A, B](t: TableRef[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. result = t[].hasKey(key) -template equalsImpl(t) = +template equalsImpl(s, t: typed): typed = if s.counter == t.counter: # different insertion orders mean different 'data' seqs, so we have # to use the slow route here: @@ -348,7 +348,9 @@ template equalsImpl(t) = return true proc `==`*[A, B](s, t: Table[A, B]): bool = - equalsImpl(t) + ## The `==` operator for hash tables. Returns ``true`` iff the content of both + ## tables contains the same key-value pairs. Insert order does not matter. + equalsImpl(s, t) proc indexBy*[A, B, C](collection: A, index: proc(x: B): C): Table[C, B] = ## Index the collection with the proc provided. @@ -436,9 +438,12 @@ proc `$`*[A, B](t: TableRef[A, B]): string = dollarImpl() proc `==`*[A, B](s, t: TableRef[A, B]): bool = + ## The `==` operator for hash tables. Returns ``true`` iff either both tables + ## are ``nil`` or none is ``nil`` and the content of both tables contains the + ## same key-value pairs. Insert order does not matter. if isNil(s): result = isNil(t) elif isNil(t): result = false - else: equalsImpl(t[]) + else: equalsImpl(s[], t[]) proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] = ## Index the collection with the proc provided. @@ -464,12 +469,16 @@ proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} = ## returns the number of keys in `t`. result = t.counter -proc clear*[A, B](t: var OrderedTable[A, B] | OrderedTableRef[A, B]) = +proc clear*[A, B](t: var OrderedTable[A, B]) = ## Resets the table so that it is empty. clearImpl() t.first = -1 t.last = -1 +proc clear*[A, B](t: var OrderedTableRef[A, B]) = + ## Resets the table so that is is empty. + clear(t[]) + template forAllOrderedPairs(yieldStmt: untyped) {.oldimmediate, dirty.} = var h = t.first while h >= 0: @@ -606,6 +615,15 @@ proc `$`*[A, B](t: OrderedTable[A, B]): string = ## The `$` operator for ordered hash tables. dollarImpl() +proc `==`*[A, B](s, t: OrderedTable[A, B]): bool = + ## The `==` operator for ordered hash tables. Both the content and the order + ## must be equal for this to return ``true``. + if s.counter == t.counter: + forAllOrderedPairs: + if s.data[h] != t.data[h]: return false + result = true + else: result = false + proc sort*[A, B](t: var OrderedTable[A, B], cmp: proc (x,y: (A, B)): int) = ## sorts `t` according to `cmp`. This modifies the internal list @@ -749,6 +767,11 @@ proc `$`*[A, B](t: OrderedTableRef[A, B]): string = ## The `$` operator for ordered hash tables. dollarImpl() +proc `==`*[A, B](s, t: OrderedTableRef[A, B]): bool = + ## The `==` operator for ordered hash tables. Both the content and the order + ## must be equal for this to return ``true``. + result = s[] == t[] + proc sort*[A, B](t: OrderedTableRef[A, B], cmp: proc (x,y: (A, B)): int) = ## sorts `t` according to `cmp`. This modifies the internal list @@ -916,6 +939,11 @@ proc `$`*[A](t: CountTable[A]): string = ## The `$` operator for count tables. dollarImpl() +proc `==`*[A](s, t: CountTable[A]): bool = + ## The `==` operator for count tables. Returns ``true`` iff both tables + ## contain the same keys with the same count. Insert order does not matter. + equalsImpl(s, t) + proc inc*[A](t: var CountTable[A], key: A, val = 1) = ## increments `t[key]` by `val`. var index = rawGet(t, key) @@ -1040,6 +1068,11 @@ proc `$`*[A](t: CountTableRef[A]): string = ## The `$` operator for count tables. dollarImpl() +proc `==`*[A](s, t: CountTableRef[A]): bool = + ## The `==` operator for count tables. Returns ``true`` iff both tables + ## contain the same keys with the same count. Insert order does not matter. + result = s[] == t[] + proc inc*[A](t: CountTableRef[A], key: A, val = 1) = ## increments `t[key]` by `val`. t[].inc(key, val) diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index 59fef4920..4f286d0ed 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -95,9 +95,24 @@ block orderedTableTest1: for key, val in mpairs(t): val = 99 for val in mvalues(t): assert val == 99 +block orderedTableTest2: + var + s = initOrderedTable[string, int]() + t = initOrderedTable[string, int]() + assert s == t + for key, val in items(data): t[key] = val + assert s != t + for key, val in items(sorteddata): s[key] = val + assert s != t + t.clear() + assert s != t + for key, val in items(sorteddata): t[key] = val + assert s == t + block countTableTest1: var s = data.toTable var t = initCountTable[string]() + for k in s.keys: t.inc(k) for k in t.keys: assert t[k] == 1 t.inc("90", 3) @@ -115,6 +130,24 @@ block countTableTest1: else: break inc i +block countTableTest2: + var + s = initCountTable[int]() + t = initCountTable[int]() + assert s == t + s.inc(1) + assert s != t + t.inc(2) + assert s != t + t.inc(1) + assert s != t + s.inc(2) + assert s == t + s.inc(1) + assert s != t + t.inc(1) + assert s == t + block mpairsTableTest1: var t = initTable[string, int]() t["a"] = 1 -- cgit 1.4.1-2-gfad0