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
This commit is contained in:
Felix Krause
2016-10-23 11:21:52 +02:00
parent 5cb50364eb
commit 73b0bb52bb
2 changed files with 70 additions and 4 deletions

View File

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

View File

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