ttables.nim 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. discard """
  2. output: '''
  3. done tableadds
  4. And we get here
  5. 1
  6. 2
  7. 3
  8. '''
  9. joinable: false
  10. """
  11. import hashes, sequtils, tables, algorithm
  12. proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted
  13. template sortedItems(t: untyped): untyped = sorted(toSeq(t))
  14. block tableDollar:
  15. # other tests should use `sortedPairs` to be robust to future table/hash
  16. # implementation changes
  17. doAssert ${1: 'a', 2: 'b'}.toTable in ["{1: 'a', 2: 'b'}", "{2: 'b', 1: 'a'}"]
  18. # test should not be joined because it takes too long.
  19. block tableadds:
  20. proc main =
  21. var tab = newTable[string, string]()
  22. for i in 0..1000:
  23. tab["key"] = "value " & $i
  24. main()
  25. echo "done tableadds"
  26. block tcounttable:
  27. # bug #2625
  28. const s_len = 32
  29. var substr_counts: CountTable[string] = initCountTable[string]()
  30. var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
  31. for i in 0..(my_string.len - s_len):
  32. let s = my_string[i..i+s_len-1]
  33. substr_counts[s] = 1
  34. # substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
  35. # substr_counts.inc(s) # This works
  36. #echo "Iteration ", i
  37. echo "And we get here"
  38. block thashes:
  39. # Test with int
  40. block:
  41. var t = initTable[int,int]()
  42. t[0] = 42
  43. t[1] = t[0] + 1
  44. assert(t[0] == 42)
  45. assert(t[1] == 43)
  46. let t2 = {1: 1, 2: 2}.toTable
  47. assert(t2[2] == 2)
  48. # Test with char
  49. block:
  50. var t = initTable[char,int]()
  51. t['0'] = 42
  52. t['1'] = t['0'] + 1
  53. assert(t['0'] == 42)
  54. assert(t['1'] == 43)
  55. let t2 = {'1': 1, '2': 2}.toTable
  56. assert(t2['2'] == 2)
  57. # Test with enum
  58. block:
  59. type
  60. E = enum eA, eB, eC
  61. var t = initTable[E,int]()
  62. t[eA] = 42
  63. t[eB] = t[eA] + 1
  64. assert(t[eA] == 42)
  65. assert(t[eB] == 43)
  66. let t2 = {eA: 1, eB: 2}.toTable
  67. assert(t2[eB] == 2)
  68. # Test with range
  69. block:
  70. type
  71. R = range[0..9]
  72. var t = initTable[R,int]() # causes warning, why?
  73. t[1] = 42 # causes warning, why?
  74. t[2] = t[1] + 1
  75. assert(t[1] == 42)
  76. assert(t[2] == 43)
  77. let t2 = {1.R: 1, 2.R: 2}.toTable
  78. assert(t2[2.R] == 2)
  79. # Test which combines the generics for tuples + ordinals
  80. block:
  81. type
  82. E = enum eA, eB, eC
  83. var t = initTable[(string, E, int, char), int]()
  84. t[("a", eA, 0, '0')] = 42
  85. t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1
  86. assert(t[("a", eA, 0, '0')] == 42)
  87. assert(t[("b", eB, 1, '1')] == 43)
  88. let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable
  89. assert(t2[("b", eB, 1, '1')] == 2)
  90. # Test to check if overloading is possible
  91. # Unfortunately, this does not seem to work for int
  92. # The same test with a custom hash(s: string) does
  93. # work though.
  94. block:
  95. proc hash(x: int): Hash {.inline.} =
  96. echo "overloaded hash"
  97. result = x
  98. var t = initTable[int, int]()
  99. t[0] = 0
  100. # Check hashability of all integer types (issue #5429)
  101. block:
  102. let intTables = (
  103. newTable[int, string](),
  104. newTable[int8, string](),
  105. newTable[int16, string](),
  106. newTable[int32, string](),
  107. newTable[int64, string](),
  108. newTable[uint, string](),
  109. newTable[uint8, string](),
  110. newTable[uint16, string](),
  111. newTable[uint32, string](),
  112. newTable[uint64, string](),
  113. )
  114. echo "1"
  115. block tindexby:
  116. doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
  117. var tbl1 = initTable[int, int]()
  118. tbl1[1] = 1
  119. tbl1[2] = 2
  120. doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
  121. type
  122. TElem = object
  123. foo: int
  124. bar: string
  125. let
  126. elem1 = TElem(foo: 1, bar: "bar")
  127. elem2 = TElem(foo: 2, bar: "baz")
  128. var tbl2 = initTable[string, TElem]()
  129. tbl2["bar"] = elem1
  130. tbl2["baz"] = elem2
  131. doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
  132. block tableconstr:
  133. # Test if the new table constructor syntax works:
  134. template ignoreExpr(e) =
  135. discard
  136. # test first class '..' syntactical citizen:
  137. ignoreExpr x <> 2..4
  138. # test table constructor:
  139. ignoreExpr({:})
  140. ignoreExpr({2: 3, "key": "value"})
  141. # NEW:
  142. assert 56 in 50..100
  143. assert 56 in ..60
  144. block ttables2:
  145. proc TestHashIntInt() =
  146. var tab = initTable[int,int]()
  147. let n = 100_000
  148. for i in 1..n:
  149. tab[i] = i
  150. for i in 1..n:
  151. var x = tab[i]
  152. if x != i : echo "not found ", i
  153. proc run1() =
  154. for i in 1 .. 50:
  155. TestHashIntInt()
  156. # bug #2107
  157. var delTab = initTable[int,int](4)
  158. for i in 1..4:
  159. delTab[i] = i
  160. delTab.del(i)
  161. delTab[5] = 5
  162. run1()
  163. echo "2"
  164. block tablesref:
  165. const
  166. data = {
  167. "34": 123456, "12": 789,
  168. "90": 343, "0": 34404,
  169. "1": 344004, "2": 344774,
  170. "3": 342244, "4": 3412344,
  171. "5": 341232144, "6": 34214544,
  172. "7": 3434544, "8": 344544,
  173. "9": 34435644, "---00": 346677844,
  174. "10": 34484, "11": 34474, "19": 34464,
  175. "20": 34454, "30": 34141244, "40": 344114,
  176. "50": 344490, "60": 344491, "70": 344492,
  177. "80": 344497}
  178. sorteddata = {
  179. "---00": 346677844,
  180. "0": 34404,
  181. "1": 344004,
  182. "10": 34484,
  183. "11": 34474,
  184. "12": 789,
  185. "19": 34464,
  186. "2": 344774, "20": 34454,
  187. "3": 342244, "30": 34141244,
  188. "34": 123456,
  189. "4": 3412344, "40": 344114,
  190. "5": 341232144, "50": 344490,
  191. "6": 34214544, "60": 344491,
  192. "7": 3434544, "70": 344492,
  193. "8": 344544, "80": 344497,
  194. "9": 34435644,
  195. "90": 343}
  196. block tableTest1:
  197. var t = newTable[tuple[x, y: int], string]()
  198. t[(0,0)] = "00"
  199. t[(1,0)] = "10"
  200. t[(0,1)] = "01"
  201. t[(1,1)] = "11"
  202. for x in 0..1:
  203. for y in 0..1:
  204. assert t[(x,y)] == $x & $y
  205. assert t.sortedPairs ==
  206. @[((x: 0, y: 0), "00"), ((x: 0, y: 1), "01"), ((x: 1, y: 0), "10"), ((x: 1, y: 1), "11")]
  207. block tableTest2:
  208. var t = newTable[string, float]()
  209. t["test"] = 1.2345
  210. t["111"] = 1.000043
  211. t["123"] = 1.23
  212. t.del("111")
  213. t["012"] = 67.9
  214. t["123"] = 1.5 # test overwriting
  215. assert t["123"] == 1.5
  216. try:
  217. echo t["111"] # deleted
  218. except KeyError:
  219. discard
  220. assert(not hasKey(t, "111"))
  221. assert "111" notin t
  222. for key, val in items(data): t[key] = val.toFloat
  223. for key, val in items(data): assert t[key] == val.toFloat
  224. block orderedTableTest1:
  225. var t = newOrderedTable[string, int](2)
  226. for key, val in items(data): t[key] = val
  227. for key, val in items(data): assert t[key] == val
  228. var i = 0
  229. # `pairs` needs to yield in insertion order:
  230. for key, val in pairs(t):
  231. assert key == data[i][0]
  232. assert val == data[i][1]
  233. inc(i)
  234. for key, val in mpairs(t): val = 99
  235. for val in mvalues(t): assert val == 99
  236. block countTableTest1:
  237. var s = data.toTable
  238. var t = newCountTable[string]()
  239. var r = newCountTable[string]()
  240. for x in [t, r]:
  241. for k in s.keys:
  242. x.inc(k)
  243. assert x[k] == 1
  244. x.inc("90", 3)
  245. x.inc("12", 2)
  246. x.inc("34", 1)
  247. assert t.largest()[0] == "90"
  248. t.sort()
  249. r.sort(SortOrder.Ascending)
  250. var ps1 = toSeq t.pairs
  251. var ps2 = toSeq r.pairs
  252. ps2.reverse()
  253. for ps in [ps1, ps2]:
  254. var i = 0
  255. for (k, v) in ps:
  256. case i
  257. of 0: assert k == "90" and v == 4
  258. of 1: assert k == "12" and v == 3
  259. of 2: assert k == "34" and v == 2
  260. else: break
  261. inc i
  262. block smallestLargestNamedFieldsTest: # bug #14918
  263. const a = [7, 8, 8]
  264. proc testNamedFields(t: CountTable | CountTableRef) =
  265. doAssert t.smallest.key == 7
  266. doAssert t.smallest.val == 1
  267. doAssert t.largest.key == 8
  268. doAssert t.largest.val == 2
  269. let t1 = toCountTable(a)
  270. testNamedFields(t1)
  271. let t2 = newCountTable(a)
  272. testNamedFields(t2)
  273. block SyntaxTest:
  274. var x = newTable[int, string]({:})
  275. discard x
  276. block nilTest:
  277. var i, j: TableRef[int, int] = nil
  278. assert i == j
  279. j = newTable[int, int]()
  280. assert i != j
  281. assert j != i
  282. i = newTable[int, int]()
  283. assert i == j
  284. proc orderedTableSortTest() =
  285. var t = newOrderedTable[string, int](2)
  286. for key, val in items(data): t[key] = val
  287. for key, val in items(data): assert t[key] == val
  288. proc cmper(x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key)
  289. t.sort(cmper)
  290. var i = 0
  291. # `pairs` needs to yield in sorted order:
  292. for key, val in pairs(t):
  293. doAssert key == sorteddata[i][0]
  294. doAssert val == sorteddata[i][1]
  295. inc(i)
  296. t.sort(cmper, order=SortOrder.Descending)
  297. i = 0
  298. for key, val in pairs(t):
  299. doAssert key == sorteddata[high(data)-i][0]
  300. doAssert val == sorteddata[high(data)-i][1]
  301. inc(i)
  302. # check that lookup still works:
  303. for key, val in pairs(t):
  304. doAssert val == t[key]
  305. # check that insert still works:
  306. t["newKeyHere"] = 80
  307. block anonZipTest:
  308. let keys = @['a','b','c']
  309. let values = @[1, 2, 3]
  310. doAssert zip(keys, values).toTable.sortedPairs == @[('a', 1), ('b', 2), ('c', 3)]
  311. block clearTableTest:
  312. var t = newTable[string, float]()
  313. t["test"] = 1.2345
  314. t["111"] = 1.000043
  315. t["123"] = 1.23
  316. assert t.len() != 0
  317. t.clear()
  318. assert t.len() == 0
  319. block clearOrderedTableTest:
  320. var t = newOrderedTable[string, int](2)
  321. for key, val in items(data): t[key] = val
  322. assert t.len() != 0
  323. t.clear()
  324. assert t.len() == 0
  325. block clearCountTableTest:
  326. var t = newCountTable[string]()
  327. t.inc("90", 3)
  328. t.inc("12", 2)
  329. t.inc("34", 1)
  330. assert t.len() != 0
  331. t.clear()
  332. assert t.len() == 0
  333. orderedTableSortTest()
  334. echo "3"
  335. block: # https://github.com/nim-lang/Nim/issues/13496
  336. template testDel(body) =
  337. block:
  338. body
  339. when t is CountTable|CountTableRef:
  340. t.inc(15, 1)
  341. t.inc(19, 2)
  342. t.inc(17, 3)
  343. t.inc(150, 4)
  344. t.del(150)
  345. else:
  346. t[15] = 1
  347. t[19] = 2
  348. t[17] = 3
  349. t[150] = 4
  350. t.del(150)
  351. doAssert t.len == 3
  352. doAssert sortedItems(t.values) == @[1, 2, 3]
  353. doAssert sortedItems(t.keys) == @[15, 17, 19]
  354. doAssert sortedPairs(t) == @[(15, 1), (17, 3), (19, 2)]
  355. var s = newSeq[int]()
  356. for v in t.values: s.add(v)
  357. assert s.len == 3
  358. doAssert sortedItems(s) == @[1, 2, 3]
  359. when t is OrderedTable|OrderedTableRef:
  360. doAssert toSeq(t.keys) == @[15, 19, 17]
  361. doAssert toSeq(t.values) == @[1,2,3]
  362. doAssert toSeq(t.pairs) == @[(15, 1), (19, 2), (17, 3)]
  363. testDel(): (var t: Table[int, int])
  364. testDel(): (let t = newTable[int, int]())
  365. testDel(): (var t: OrderedTable[int, int])
  366. testDel(): (let t = newOrderedTable[int, int]())
  367. testDel(): (var t: CountTable[int])
  368. testDel(): (let t = newCountTable[int]())
  369. block testNonPowerOf2:
  370. var a = initTable[int, int](7)
  371. a[1] = 10
  372. assert a[1] == 10
  373. var b = initTable[int, int](9)
  374. b[1] = 10
  375. assert b[1] == 10
  376. block emptyOrdered:
  377. var t1: OrderedTable[int, string]
  378. var t2: OrderedTable[int, string]
  379. assert t1 == t2