diff --git a/changelog.md b/changelog.md index fe44dc3401..f1671f160e 100644 --- a/changelog.md +++ b/changelog.md @@ -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 diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 7d1633e7d2..22c8027b9d 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