diff options
author | Araq <rumpf_a@web.de> | 2013-01-12 23:59:29 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-01-12 23:59:29 +0100 |
commit | b3e70febb476a4e6512ee499aba130008c3fa1c8 (patch) | |
tree | 084bb6950d9651e565626e3a53a6cd495b394cd2 | |
parent | 1115c8bdf8204cdf58fd9a488e8b559b6f4be16b (diff) | |
download | Nim-b3e70febb476a4e6512ee499aba130008c3fa1c8.tar.gz |
'sort' for ordered tables
-rwxr-xr-x | lib/pure/collections/tables.nim | 48 | ||||
-rwxr-xr-x | tests/run/ttables.nim | 39 |
2 files changed, 86 insertions, 1 deletions
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 3b252f1d2..4290af08a 100755 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -308,6 +308,52 @@ proc `$`*[A, B](t: TOrderedTable[A, B]): string = ## The `$` operator for ordered hash tables. dollarImpl() +proc sort*[A, B](t: var TOrderedTable[A, B], + cmp: proc (x,y: tuple[key: A, val: B]): int) = + ## sorts `t` according to `cmp`. This modifies the internal list + ## that kept the insertion order, so insertion order is lost after this + ## call but key lookup and insertions remain possible after `sort` (in + ## contrast to the `sort` for count tables). + var list = t.first + var + p, q, e, tail, oldhead: int + nmerges, psize, qsize, i: int + if t.counter == 0: return + var insize = 1 + while true: + p = list; oldhead = list + list = -1; tail = -1; nmerges = 0 + while p >= 0: + inc(nmerges) + q = p + psize = 0 + i = 0 + while i < insize: + inc(psize) + q = t.data[q].next + if q < 0: break + inc(i) + qsize = insize + while psize > 0 or (qsize > 0 and q >= 0): + if psize == 0: + e = q; q = t.data[q].next; dec(qsize) + elif qsize == 0 or q < 0: + e = p; p = t.data[p].next; dec(psize) + elif cmp((t.data[p].key, t.data[p].val), + (t.data[q].key, t.data[q].val)) <= 0: + e = p; p = t.data[p].next; dec(psize) + else: + e = q; q = t.data[q].next; dec(qsize) + if tail >= 0: t.data[tail].next = e + else: list = e + tail = e + p = q + t.data[tail].next = -1 + if nmerges <= 1: break + insize = insize * 2 + t.first = list + t.last = tail + # ------------------------------ count tables ------------------------------- type diff --git a/tests/run/ttables.nim b/tests/run/ttables.nim index 3eb17a803..681ff5424 100755 --- a/tests/run/ttables.nim +++ b/tests/run/ttables.nim @@ -19,6 +19,25 @@ const "50": 344490, "60": 344491, "70": 344492, "80": 344497} + sorteddata = { + "---00": 346677844, + "0": 34404, + "1": 344004, + "10": 34484, + "11": 34474, + "12": 789, + "19": 34464, + "2": 344774, "20": 34454, + "3": 342244, "30": 34141244, + "34": 123456, + "4": 3412344, "40": 344114, + "5": 341232144, "50": 344490, + "6": 34214544, "60": 344491, + "7": 3434544, "70": 344492, + "8": 344544, "80": 344497, + "9": 34435644, + "90": 343} + block tableTest1: var t = initTable[tuple[x, y: int], string]() t[(0,0)] = "00" @@ -86,5 +105,25 @@ block countTableTest1: block SyntaxTest: var x = toTable[int, string]({:}) +proc orderedTableSortTest() = + var t = initOrderedTable[string, int](2) + for key, val in items(data): t[key] = val + for key, val in items(data): assert t[key] == val + t.sort(proc (x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key)) + var i = 0 + # `pairs` needs to yield in sorted order: + for key, val in pairs(t): + doAssert key == sorteddata[i][0] + doAssert val == sorteddata[i][1] + inc(i) + + # check that lookup still works: + for key, val in pairs(t): + doAssert val == t[key] + # check that insert still works: + t["newKeyHere"] = 80 + + +orderedTableSortTest() echo "true" |