diff options
author | Miran <narimiran@disroot.org> | 2019-11-08 16:35:27 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-11-08 16:35:27 +0100 |
commit | 6958248efe22a7be45eede4d59ba3f7f8bcf7c01 (patch) | |
tree | 3e079aba8a14051d6173204fe1dc9d812ea5ea06 /lib | |
parent | 1e71c1369730dade637b7a87987855d4e7acb4d1 (diff) | |
download | Nim-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.nim | 152 |
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 |