discard """
output: '''
done tableadds
And we get here
1
2
3
'''
joinable: false
"""
import hashes, sequtils, tables, algorithm
proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted
template sortedItems(t: untyped): untyped = sorted(toSeq(t))
block tableDollar:
# other tests should use `sortedPairs` to be robust to future table/hash
# implementation changes
doAssert ${1: 'a', 2: 'b'}.toTable in ["{1: 'a', 2: 'b'}", "{2: 'b', 1: 'a'}"]
# test should not be joined because it takes too long.
block tableadds:
proc main =
var tab = newTable[string, string]()
for i in 0..1000:
tab.add "key", "value " & $i
main()
echo "done tableadds"
block tcounttable:
# bug #2625
const s_len = 32
var substr_counts: CountTable[string] = initCountTable[string]()
var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
for i in 0..(my_string.len - s_len):
let s = my_string[i..i+s_len-1]
substr_counts[s] = 1
# substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
# substr_counts.inc(s) # This works
#echo "Iteration ", i
echo "And we get here"
block thashes:
# Test with int
block:
var t = initTable[int,int]()
t[0] = 42
t[1] = t[0] + 1
assert(t[0] == 42)
assert(t[1] == 43)
let t2 = {1: 1, 2: 2}.toTable
assert(t2[2] == 2)
# Test with char
block:
var t = initTable[char,int]()
t['0'] = 42
t['1'] = t['0'] + 1
assert(t['0'] == 42)
assert(t['1'] == 43)
let t2 = {'1': 1, '2': 2}.toTable
assert(t2['2'] == 2)
# Test with enum
block:
type
E = enum eA, eB, eC
var t = initTable[E,int]()
t[eA] = 42
t[eB] = t[eA] + 1
assert(t[eA] == 42)
assert(t[eB] == 43)
let t2 = {eA: 1, eB: 2}.toTable
assert(t2[eB] == 2)
# Test with range
block:
type
R = range[0..9]
var t = initTable[R,int]() # causes warning, why?
t[1] = 42 # causes warning, why?
t[2] = t[1] + 1
assert(t[1] == 42)
assert(t[2] == 43)
let t2 = {1.R: 1, 2.R: 2}.toTable
assert(t2[2.R] == 2)
# Test which combines the generics for tuples + ordinals
block:
type
E = enum eA, eB, eC
var t = initTable[(string, E, int, char), int]()
t[("a", eA, 0, '0')] = 42
t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1
assert(t[("a", eA, 0, '0')] == 42)
assert(t[("b", eB, 1, '1')] == 43)
let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable
assert(t2[("b", eB, 1, '1')] == 2)
# Test to check if overloading is possible
# Unfortunately, this does not seem to work for int
# The same test with a custom hash(s: string) does
# work though.
block:
proc hash(x: int): Hash {.inline.} =
echo "overloaded hash"
result = x
var t = initTable[int, int]()
t[0] = 0
# Check hashability of all integer types (issue #5429)
block:
let intTables = (
newTable[int, string](),
newTable[int8, string](),
newTable[int16, string](),
newTable[int32, string](),
newTable[int64, string](),
newTable[uint, string](),
newTable[uint8, string](),
newTable[uint16, string](),
newTable[uint32, string](),
newTable[uint64, string](),
)
echo "1"
block tindexby:
doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
var tbl1 = initTable[int, int]()
tbl1.add(1,1)
tbl1.add(2,2)
doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
type
TElem = object
foo: int
bar: string
let
elem1 = TElem(foo: 1, bar: "bar")
elem2 = TElem(foo: 2, bar: "baz")
var tbl2 = initTable[string, TElem]()
tbl2.add("bar", elem1)
tbl2.add("baz", elem2)
doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
block tableconstr:
# Test if the new table constructor syntax works:
template ignoreExpr(e) =
discard
# test first class '..' syntactical citizen:
ignoreExpr x <> 2..4
# test table constructor:
ignoreExpr({:})
ignoreExpr({2: 3, "key": "value"})
# NEW:
assert 56 in 50..100
assert 56 in ..60
block ttables2:
proc TestHashIntInt() =
var tab = initTable[int,int]()
let n = 100_000
for i in 1..n:
tab[i] = i
for i in 1..n:
var x = tab[i]
if x != i : echo "not found ", i
proc run1() =
for i in 1 .. 50:
TestHashIntInt()
# bug #2107
var delTab = initTable[int,int](4)
for i in 1..4:
delTab[i] = i
delTab.del(i)
delTab[5] = 5
run1()
echo "2"
block allValues:
var t: Table[int, string]
var key = 0
let n = 1000
for i in 0..<n: t.add(i, $i)
const keys = [0, -1, 12]
for i in 0..1:
for key in keys:
t.add(key, $key & ":" & $i)
for i in 0..<n:
if i notin keys:
t.del(i)
doAssert t.sortedPairs == @[(-1, "-1:0"), (-1, "-1:1"), (0, "0"), (0, "0:0"), (0, "0:1"), (12, "12"), (12, "12:0"), (12, "12:1")]
doAssert sortedItems(t.allValues(0)) == @["0", "0:0", "0:1"]
doAssert sortedItems(t.allValues(-1)) == @["-1:0", "-1:1"]
doAssert sortedItems(t.allValues(12)) == @["12", "12:0", "12:1"]
doAssert sortedItems(t.allValues(1)) == @[]
block tablesref:
const
data = {
"34": 123456, "12": 789,
"90": 343, "0": 34404,
"1": 344004, "2": 344774,
"3": 342244, "4": 3412344,
"5": 341232144, "6": 34214544,
"7": 3434544, "8": 344544,
"9": 34435644, "---00": 346677844,
"10": 34484, "11": 34474, "19": 34464,
"20": 34454, "30": 34141244, "40": 344114,
"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 = newTable[tuple[x, y: int], string]()
t[(0,0)] = "00"
t[(1,0)] = "10"
t[(0,1)] = "01"
t[(1,1)] = "11"
for x in 0..1:
for y in 0..1:
assert t[(x,y)] == $x & $y
assert t.sortedPairs ==
@[((x: 0, y: 0), "00"), ((x: 0, y: 1), "01"), ((x: 1, y: 0), "10"), ((x: 1, y: 1), "11")]
block tableTest2:
var t = newTable[string, float]()
t["test"] = 1.2345
t["111"] = 1.000043
t["123"] = 1.23
t.del("111")
t["012"] = 67.9
t["123"] = 1.5 # test overwriting
assert t["123"] == 1.5
try:
echo t["111"] # deleted
except KeyError:
discard
assert(not hasKey(t, "111"))
assert "111" notin t
for key, val in items(data): t[key] = val.toFloat
for key, val in items(data): assert t[key] == val.toFloat
block orderedTableTest1:
var t = newOrderedTable[string, int](2)
for key, val in items(data): t[key] = val
for key, val in items(data): assert t[key] == val
var i = 0
# `pairs` needs to yield in insertion order:
for key, val in pairs(t):
assert key == data[i][0]
assert val == data[i][1]
inc(i)
for key, val in mpairs(t): val = 99
for val in mvalues(t): assert val == 99
block countTableTest1:
var s = data.toTable
var t = newCountTable[string]()
var r = newCountTable[string]()
for x in [t, r]:
for k in s.keys:
x.inc(k)
assert x[k] == 1
x.inc("90", 3)
x.inc("12", 2)
x.inc("34", 1)
assert t.largest()[0] == "90"
t.sort()
r.sort(SortOrder.Ascending)
var ps1 = toSeq t.pairs
var ps2 = toSeq r.pairs
ps2.reverse()
for ps in [ps1, ps2]:
var i = 0
for (k, v) in ps:
case i
of 0: assert k == "90" and v == 4
of 1: assert k == "12" and v == 3
of 2: assert k == "34" and v == 2
else: break
inc i
block SyntaxTest:
var x = newTable[int, string]({:})
discard x
block nilTest:
var i, j: TableRef[int, int] = nil
assert i == j
j = newTable[int, int]()
assert i != j
assert j != i
i = newTable[int, int]()
assert i == j
proc orderedTableSortTest() =
var t = newOrderedTable[string, int](2)
for key, val in items(data): t[key] = val
for key, val in items(data): assert t[key] == val
proc cmper(x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key)
t.sort(cmper)
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)
t.sort(cmper, order=SortOrder.Descending)
i = 0
for key, val in pairs(t):
doAssert key == sorteddata[high(data)-i][0]
doAssert val == sorteddata[high(data)-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
block anonZipTest:
let keys = @['a','b','c']
let values = @[1, 2, 3]
doAssert zip(keys, values).toTable.sortedPairs == @[('a', 1), ('b', 2), ('c', 3)]
block clearTableTest:
var t = newTable[string, float]()
t["test"] = 1.2345
t["111"] = 1.000043
t["123"] = 1.23
assert t.len() != 0
t.clear()
assert t.len() == 0
block clearOrderedTableTest:
var t = newOrderedTable[string, int](2)
for key, val in items(data): t[key] = val
assert t.len() != 0
t.clear()
assert t.len() == 0
block clearCountTableTest:
var t = newCountTable[string]()
t.inc("90", 3)
t.inc("12", 2)
t.inc("34", 1)
assert t.len() != 0
t.clear()
assert t.len() == 0
orderedTableSortTest()
echo "3"
block: # https://github.com/nim-lang/Nim/issues/13496
template testDel(body) =
block:
body
when t is CountTable|CountTableRef:
t.inc(15, 1)
t.inc(19, 2)
t.inc(17, 3)
t.inc(150, 4)
t.del(150)
else:
t[15] = 1
t[19] = 2
t[17] = 3
t[150] = 4
t.del(150)
doAssert t.len == 3
doAssert sortedItems(t.values) == @[1, 2, 3]
doAssert sortedItems(t.keys) == @[15, 17, 19]
doAssert sortedPairs(t) == @[(15, 1), (17, 3), (19, 2)]
var s = newSeq[int]()
for v in t.values: s.add(v)
assert s.len == 3
doAssert sortedItems(s) == @[1, 2, 3]
when t is OrderedTable|OrderedTableRef:
doAssert toSeq(t.keys) == @[15, 19, 17]
doAssert toSeq(t.values) == @[1,2,3]
doAssert toSeq(t.pairs) == @[(15, 1), (19, 2), (17, 3)]
testDel(): (var t: Table[int, int])
testDel(): (let t = newTable[int, int]())
testDel(): (var t: OrderedTable[int, int])
testDel(): (let t = newOrderedTable[int, int]())
testDel(): (var t: CountTable[int])
testDel(): (let t = newCountTable[int]())