summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorMiran <narimiran@disroot.org>2019-11-08 16:35:27 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-11-08 16:35:27 +0100
commit6958248efe22a7be45eede4d59ba3f7f8bcf7c01 (patch)
tree3e079aba8a14051d6173204fe1dc9d812ea5ea06 /lib
parent1e71c1369730dade637b7a87987855d4e7acb4d1 (diff)
downloadNim-6958248efe22a7be45eede4d59ba3f7f8bcf7c01.tar.gz
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]
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/collections/tables.nim152
1 files changed, 148 insertions, 4 deletions
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 7d1633e7d..22c8027b9 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -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