'sort' for ordered tables

This commit is contained in:
Araq
2013-01-12 23:59:29 +01:00
parent 1115c8bdf8
commit b3e70febb4
2 changed files with 86 additions and 1 deletions

View File

@@ -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

View File

@@ -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"