fix #12519: introduce OrderedTable.take, CountTable.del, CountTable.take (#12600)

* add OrderedTable.take

* add CountTable.del and CountTable.take

* add .since pragma to the introduced public procs

* add changelog entry [ci skip]
This commit is contained in:
Miran
2019-11-08 16:35:27 +01:00
committed by Andreas Rumpf
parent 1e71c13697
commit 6958248efe
2 changed files with 150 additions and 5 deletions

View File

@@ -32,7 +32,8 @@
- `system.writeFile` has been overloaded to also support `openarray[byte]`.
- Added overloaded `strformat.fmt` macro that use specified characters as
delimiter instead of '{' and '}'.
- introduced new procs in `tables.nim`: `OrderedTable.take`, `CountTable.del`,
`CountTable.take`
## Library changes

View File

@@ -1488,6 +1488,7 @@ proc del*[A, B](t: var OrderedTable[A, B], key: A) =
## O(n) complexity.
##
## See also:
## * `take proc<#take,OrderedTable[A,B],A,B>`_
## * `clear proc<#clear,OrderedTable[A,B]>`_ to empty the whole table
runnableExamples:
var a = {'a': 5, 'b': 9, 'c': 13}.toOrderedTable
@@ -1513,11 +1514,42 @@ proc del*[A, B](t: var OrderedTable[A, B], key: A) =
rawInsert(t, t.data, n[h].key, n[h].val, n[h].hcode, j)
h = nxt
proc take*[A, B](t: var OrderedTable[A, B], key: A, val: var B): bool {.since: (1, 1).} =
## Deletes the ``key`` from the table.
## Returns ``true``, if the ``key`` existed, and sets ``val`` to the
## mapping of the key. Otherwise, returns ``false``, and the ``val`` is
## unchanged.
##
## O(n) complexity.
##
## See also:
## * `del proc<#del,OrderedTable[A,B],A>`_
## * `clear proc<#clear,OrderedTable[A,B]>`_ to empty the whole table
runnableExamples:
var
a = {'c': 5, 'b': 9, 'a': 13}.toOrderedTable
i: int
doAssert a.take('b', i) == true
doAssert a == {'c': 5, 'a': 13}.toOrderedTable
doAssert i == 9
i = 0
doAssert a.take('z', i) == false
doAssert a == {'c': 5, 'a': 13}.toOrderedTable
doAssert i == 0
var hc: Hash
var index = rawGet(t, key, hc)
result = index >= 0
if result:
val = move(t.data[index].val)
del(t, key)
proc clear*[A, B](t: var OrderedTable[A, B]) =
## Resets the table so that it is empty.
##
## See also:
## * `del proc<#del,OrderedTable[A,B],A>`_
## * `take proc<#take,OrderedTable[A,B],A,B>`_
runnableExamples:
var a = {'a': 5, 'b': 9, 'c': 13}.toOrderedTable
doAssert len(a) == 3
@@ -1942,7 +1974,7 @@ proc add*[A, B](t: OrderedTableRef[A, B], key: A, val: B) =
## (key, value) pair in the table without introducing duplicates.
t[].add(key, val)
proc del*[A, B](t: var OrderedTableRef[A, B], key: A) =
proc del*[A, B](t: OrderedTableRef[A, B], key: A) =
## Deletes ``key`` from hash table ``t``. Does nothing if the key does not exist.
##
## See also:
@@ -1956,11 +1988,34 @@ proc del*[A, B](t: var OrderedTableRef[A, B], key: A) =
t[].del(key)
proc clear*[A, B](t: var OrderedTableRef[A, B]) =
proc take*[A, B](t: OrderedTableRef[A, B], key: A, val: var B): bool {.since: (1, 1).} =
## Deletes the ``key`` from the table.
## Returns ``true``, if the ``key`` existed, and sets ``val`` to the
## mapping of the key. Otherwise, returns ``false``, and the ``val`` is
## unchanged.
##
## See also:
## * `del proc<#del,OrderedTableRef[A,B],A>`_
## * `clear proc<#clear,OrderedTableRef[A,B]>`_ to empty the whole table
runnableExamples:
var
a = {'c': 5, 'b': 9, 'a': 13}.newOrderedTable
i: int
doAssert a.take('b', i) == true
doAssert a == {'c': 5, 'a': 13}.newOrderedTable
doAssert i == 9
i = 0
doAssert a.take('z', i) == false
doAssert a == {'c': 5, 'a': 13}.newOrderedTable
doAssert i == 0
take(t[], key, val)
proc clear*[A, B](t: OrderedTableRef[A, B]) =
## Resets the table so that it is empty.
##
## See also:
## * `del proc<#del,OrderedTable[A,B],A>`_
## * `del proc<#del,OrderedTableRef[A,B],A>`_
runnableExamples:
var a = {'a': 5, 'b': 9, 'c': 13}.newOrderedTable
doAssert len(a) == 3
@@ -2169,6 +2224,19 @@ proc enlarge[A](t: var CountTable[A]) =
if t.data[i].val != 0: ctRawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n)
proc remove[A](t: var CountTable[A], key: A) =
var n: seq[tuple[key: A, val: int]]
newSeq(n, len(t.data))
var removed: bool
for i in countup(0, high(t.data)):
if t.data[i].val != 0:
if t.data[i].key != key:
ctRawInsert(t, n, t.data[i].key, t.data[i].val)
else:
removed = true
swap(t.data, n)
if removed: dec(t.counter)
proc rawGet[A](t: CountTable[A], key: A): int =
if t.data.len == 0:
return -1
@@ -2322,8 +2390,57 @@ proc len*[A](t: CountTable[A]): int =
## Returns the number of keys in ``t``.
result = t.counter
proc del*[A](t: var CountTable[A], key: A) {.since: (1, 1).} =
## Deletes ``key`` from table ``t``. Does nothing if the key does not exist.
##
## O(n) complexity.
##
## See also:
## * `take proc<#take,CountTable[A],A,int>`_
## * `clear proc<#clear,CountTable[A]>`_ to empty the whole table
runnableExamples:
var a = toCountTable("aabbbccccc")
a.del('b')
assert a == toCountTable("aaccccc")
a.del('b')
assert a == toCountTable("aaccccc")
a.del('c')
assert a == toCountTable("aa")
remove(t, key)
proc take*[A](t: var CountTable[A], key: A, val: var int): bool {.since: (1, 1).} =
## Deletes the ``key`` from the table.
## Returns ``true``, if the ``key`` existed, and sets ``val`` to the
## mapping of the key. Otherwise, returns ``false``, and the ``val`` is
## unchanged.
##
## O(n) complexity.
##
## See also:
## * `del proc<#del,CountTable[A],A>`_
## * `clear proc<#clear,CountTable[A]>`_ to empty the whole table
runnableExamples:
var a = toCountTable("aabbbccccc")
var i = 0
assert a.take('b', i)
assert i == 3
i = 99
assert not a.take('b', i)
assert i == 99
var index = rawGet(t, key)
result = index >= 0
if result:
val = move(t.data[index].val)
remove(t, key)
proc clear*[A](t: var CountTable[A]) =
## Resets the table so that it is empty.
##
## See also:
## * `del proc<#del,CountTable[A],A>`_
## * `take proc<#take,CountTable[A],A,int>`_
clearImpl()
t.isSorted = false
@@ -2612,9 +2729,36 @@ proc len*[A](t: CountTableRef[A]): int =
## Returns the number of keys in ``t``.
result = t.counter
proc del*[A](t: CountTableRef[A], key: A) {.since: (1, 1).} =
## Deletes ``key`` from table ``t``. Does nothing if the key does not exist.
##
## O(n) complexity.
##
## See also:
## * `take proc<#take,CountTableRef[A],A,int>`_
## * `clear proc<#clear,CountTableRef[A]>`_ to empty the whole table
del(t[], key)
proc take*[A](t: CountTableRef[A], key: A, val: var int): bool {.since: (1, 1).} =
## Deletes the ``key`` from the table.
## Returns ``true``, if the ``key`` existed, and sets ``val`` to the
## mapping of the key. Otherwise, returns ``false``, and the ``val`` is
## unchanged.
##
## O(n) complexity.
##
## See also:
## * `del proc<#del,CountTableRef[A],A>`_
## * `clear proc<#clear,CountTableRef[A]>`_ to empty the whole table
take(t[], key, val)
proc clear*[A](t: CountTableRef[A]) =
## Resets the table so that it is empty.
clearImpl()
##
## See also:
## * `del proc<#del,CountTableRef[A],A>`_
## * `take proc<#take,CountTableRef[A],A,int>`_
clear(t[])
proc sort*[A](t: CountTableRef[A], order = SortOrder.Descending) =
## Sorts the count table so that, by default, the entry with the