summary refs log tree commit diff stats
path: root/lib/pure/collections/tables.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-01-12 23:59:29 +0100
committerAraq <rumpf_a@web.de>2013-01-12 23:59:29 +0100
commitb3e70febb476a4e6512ee499aba130008c3fa1c8 (patch)
tree084bb6950d9651e565626e3a53a6cd495b394cd2 /lib/pure/collections/tables.nim
parent1115c8bdf8204cdf58fd9a488e8b559b6f4be16b (diff)
downloadNim-b3e70febb476a4e6512ee499aba130008c3fa1c8.tar.gz
'sort' for ordered tables
Diffstat (limited to 'lib/pure/collections/tables.nim')
-rwxr-xr-xlib/pure/collections/tables.nim48
1 files changed, 47 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