123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973 |
- #
- #
- # Nim's Runtime Library
- # (c) Copyright 2015 Andreas Rumpf
- #
- # See the file "copying.txt", included in this
- # distribution, for details about the copyright.
- #
- ## The `tables` module implements variants of an efficient `hash table`:idx:
- ## (also often named `dictionary`:idx: in other programming languages) that is
- ## a mapping from keys to values.
- ##
- ## There are several different types of hash tables available:
- ## * `Table<#Table>`_ is the usual hash table,
- ## * `OrderedTable<#OrderedTable>`_ is like `Table` but remembers insertion order,
- ## * `CountTable<#CountTable>`_ is a mapping from a key to its number of occurrences
- ##
- ## For consistency with every other data type in Nim these have **value**
- ## semantics, this means that `=` performs a copy of the hash table.
- ##
- ## For `ref semantics<manual.html#types-reference-and-pointer-types>`_
- ## use their `Ref` variants: `TableRef<#TableRef>`_,
- ## `OrderedTableRef<#OrderedTableRef>`_, and `CountTableRef<#CountTableRef>`_.
- ##
- ## To give an example, when `a` is a `Table`, then `var b = a` gives `b`
- ## as a new independent table. `b` is initialised with the contents of `a`.
- ## Changing `b` does not affect `a` and vice versa:
- runnableExamples:
- var
- a = {1: "one", 2: "two"}.toTable # creates a Table
- b = a
- assert a == b
- b[3] = "three"
- assert 3 notin a
- assert 3 in b
- assert a != b
- ## On the other hand, when `a` is a `TableRef` instead, then changes to `b`
- ## also affect `a`. Both `a` and `b` **ref** the same data structure:
- runnableExamples:
- var
- a = {1: "one", 2: "two"}.newTable # creates a TableRef
- b = a
- assert a == b
- b[3] = "three"
- assert 3 in a
- assert 3 in b
- assert a == b
- ##
- ## ----
- ##
- ## # Basic usage
- ## ## Table
- runnableExamples:
- from std/sequtils import zip
- let
- names = ["John", "Paul", "George", "Ringo"]
- years = [1940, 1942, 1943, 1940]
- var beatles = initTable[string, int]()
- for pairs in zip(names, years):
- let (name, birthYear) = pairs
- beatles[name] = birthYear
- assert beatles == {"George": 1943, "Ringo": 1940, "Paul": 1942, "John": 1940}.toTable
- var beatlesByYear = initTable[int, seq[string]]()
- for pairs in zip(years, names):
- let (birthYear, name) = pairs
- if not beatlesByYear.hasKey(birthYear):
- # if a key doesn't exist, we create one with an empty sequence
- # before we can add elements to it
- beatlesByYear[birthYear] = @[]
- beatlesByYear[birthYear].add(name)
- assert beatlesByYear == {1940: @["John", "Ringo"], 1942: @["Paul"], 1943: @["George"]}.toTable
- ## ## OrderedTable
- ## `OrderedTable<#OrderedTable>`_ is used when it is important to preserve
- ## the insertion order of keys.
- runnableExamples:
- let
- a = [('z', 1), ('y', 2), ('x', 3)]
- ot = a.toOrderedTable # ordered tables
- assert $ot == """{'z': 1, 'y': 2, 'x': 3}"""
- ## ## CountTable
- ## `CountTable<#CountTable>`_ is useful for counting number of items of some
- ## container (e.g. string, sequence or array), as it is a mapping where the
- ## items are the keys, and their number of occurrences are the values.
- ## For that purpose `toCountTable proc<#toCountTable,openArray[A]>`_
- ## comes handy:
- runnableExamples:
- let myString = "abracadabra"
- let letterFrequencies = toCountTable(myString)
- assert $letterFrequencies == "{'a': 5, 'd': 1, 'b': 2, 'r': 2, 'c': 1}"
- ## The same could have been achieved by manually iterating over a container
- ## and increasing each key's value with `inc proc
- ## <#inc,CountTable[A],A,int>`_:
- runnableExamples:
- let myString = "abracadabra"
- var letterFrequencies = initCountTable[char]()
- for c in myString:
- letterFrequencies.inc(c)
- assert $letterFrequencies == "{'d': 1, 'r': 2, 'c': 1, 'a': 5, 'b': 2}"
- ##
- ## ----
- ##
- ## ## Hashing
- ##
- ## If you are using simple standard types like `int` or `string` for the
- ## keys of the table you won't have any problems, but as soon as you try to use
- ## a more complex object as a key you will be greeted by a strange compiler
- ## error:
- ##
- ## Error: type mismatch: got (Person)
- ## but expected one of:
- ## hashes.hash(x: openArray[A]): Hash
- ## hashes.hash(x: int): Hash
- ## hashes.hash(x: float): Hash
- ##
- ## What is happening here is that the types used for table keys require to have
- ## a `hash()` proc which will convert them to a `Hash <hashes.html#Hash>`_
- ## value, and the compiler is listing all the hash functions it knows.
- ## Additionally there has to be a `==` operator that provides the same
- ## semantics as its corresponding `hash` proc.
- ##
- ## After you add `hash` and `==` for your custom type everything will work.
- ## Currently, however, `hash` for objects is not defined, whereas
- ## `system.==` for objects does exist and performs a "deep" comparison (every
- ## field is compared) which is usually what you want. So in the following
- ## example implementing only `hash` suffices:
- runnableExamples:
- import std/hashes
- type
- Person = object
- firstName, lastName: string
- proc hash(x: Person): Hash =
- ## Piggyback on the already available string hash proc.
- ##
- ## Without this proc nothing works!
- result = x.firstName.hash !& x.lastName.hash
- result = !$result
- var
- salaries = initTable[Person, int]()
- p1, p2: Person
- p1.firstName = "Jon"
- p1.lastName = "Ross"
- salaries[p1] = 30_000
- p2.firstName = "소진"
- p2.lastName = "박"
- salaries[p2] = 45_000
- ##
- ## ----
- ##
- ## # See also
- ##
- ## * `json module<json.html>`_ for table-like structure which allows
- ## heterogeneous members
- ## * `strtabs module<strtabs.html>`_ for efficient hash tables
- ## mapping from strings to strings
- ## * `hashes module<hashes.html>`_ for helper functions for hashing
- import std/private/since
- import std/[hashes, math, algorithm]
- when not defined(nimHasEffectsOf):
- {.pragma: effectsOf.}
- type
- KeyValuePair[A, B] = tuple[hcode: Hash, key: A, val: B]
- KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]]
- Table*[A, B] = object
- ## Generic hash table, consisting of a key-value pair.
- ##
- ## `data` and `counter` are internal implementation details which
- ## can't be accessed.
- ##
- ## For creating an empty Table, use `initTable proc<#initTable>`_.
- data: KeyValuePairSeq[A, B]
- counter: int
- TableRef*[A, B] = ref Table[A, B] ## Ref version of `Table<#Table>`_.
- ##
- ## For creating a new empty TableRef, use `newTable proc
- ## <#newTable>`_.
- # ------------------------------ helpers ---------------------------------
- # Do NOT move these to tableimpl.nim, because sharedtables uses that
- # file and has its own implementation.
- template maxHash(t): untyped = high(t.data)
- template dataLen(t): untyped = len(t.data)
- include tableimpl
- proc raiseKeyError[T](key: T) {.noinline, noreturn.} =
- when compiles($key):
- raise newException(KeyError, "key not found: " & $key)
- else:
- raise newException(KeyError, "key not found")
- template get(t, key): untyped =
- ## retrieves the value at `t[key]`. The value can be modified.
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- mixin rawGet
- var hc: Hash
- var index = rawGet(t, key, hc)
- if index >= 0: result = t.data[index].val
- else:
- raiseKeyError(key)
- proc enlarge[A, B](t: var Table[A, B]) =
- var n: KeyValuePairSeq[A, B]
- newSeq(n, len(t.data) * growthFactor)
- swap(t.data, n)
- for i in countup(0, high(n)):
- let eh = n[i].hcode
- if isFilled(eh):
- var j: Hash = eh and maxHash(t)
- while isFilled(t.data[j].hcode):
- j = nextTry(j, maxHash(t))
- when defined(js):
- rawInsert(t, t.data, n[i].key, n[i].val, eh, j)
- else:
- rawInsert(t, t.data, move n[i].key, move n[i].val, eh, j)
- # -------------------------------------------------------------------
- # ------------------------------ Table ------------------------------
- # -------------------------------------------------------------------
- proc initTable*[A, B](initialSize = defaultInitialSize): Table[A, B] =
- ## Creates a new hash table that is empty.
- ##
- ## Starting from Nim v0.20, tables are initialized by default and it is
- ## not necessary to call this function explicitly.
- ##
- ## See also:
- ## * `toTable proc<#toTable,openArray[]>`_
- ## * `newTable proc<#newTable>`_ for creating a `TableRef`
- runnableExamples:
- let
- a = initTable[int, string]()
- b = initTable[char, seq[int]]()
- result = default(Table[A, B])
- initImpl(result, initialSize)
- proc `[]=`*[A, B](t: var Table[A, B], key: A, val: sink B) =
- ## Inserts a `(key, value)` pair into `t`.
- ##
- ## See also:
- ## * `[] proc<#[],Table[A,B],A>`_ for retrieving a value of a key
- ## * `hasKeyOrPut proc<#hasKeyOrPut,Table[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,Table[A,B],A,B>`_
- ## * `del proc<#del,Table[A,B],A>`_ for removing a key from the table
- runnableExamples:
- var a = initTable[char, int]()
- a['x'] = 7
- a['y'] = 33
- doAssert a == {'x': 7, 'y': 33}.toTable
- putImpl(enlarge)
- proc toTable*[A, B](pairs: openArray[(A, B)]): Table[A, B] =
- ## Creates a new hash table that contains the given `pairs`.
- ##
- ## `pairs` is a container consisting of `(key, value)` tuples.
- ##
- ## See also:
- ## * `initTable proc<#initTable>`_
- ## * `newTable proc<#newTable,openArray[]>`_ for a `TableRef` version
- runnableExamples:
- let a = [('a', 5), ('b', 9)]
- let b = toTable(a)
- assert b == {'a': 5, 'b': 9}.toTable
- result = initTable[A, B](pairs.len)
- for key, val in items(pairs): result[key] = val
- proc `[]`*[A, B](t: Table[A, B], key: A): lent B =
- ## Retrieves the value at `t[key]`.
- ##
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- ## One can check with `hasKey proc<#hasKey,Table[A,B],A>`_ whether
- ## the key exists.
- ##
- ## See also:
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]=,Table[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,Table[A,B],A>`_ for checking if a key is in
- ## the table
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toTable
- doAssert a['a'] == 5
- doAssertRaises(KeyError):
- echo a['z']
- get(t, key)
- proc `[]`*[A, B](t: var Table[A, B], key: A): var B =
- ## Retrieves the value at `t[key]`. The value can be modified.
- ##
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- ##
- ## See also:
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]=,Table[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,Table[A,B],A>`_ for checking if a key is in
- ## the table
- get(t, key)
- proc hasKey*[A, B](t: Table[A, B], key: A): bool =
- ## Returns true if `key` is in the table `t`.
- ##
- ## See also:
- ## * `contains proc<#contains,Table[A,B],A>`_ for use with the `in` operator
- ## * `[] proc<#[],Table[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toTable
- doAssert a.hasKey('a') == true
- doAssert a.hasKey('z') == false
- var hc: Hash
- result = rawGet(t, key, hc) >= 0
- proc contains*[A, B](t: Table[A, B], key: A): bool =
- ## Alias of `hasKey proc<#hasKey,Table[A,B],A>`_ for use with
- ## the `in` operator.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toTable
- doAssert 'b' in a == true
- doAssert a.contains('z') == false
- return hasKey[A, B](t, key)
- proc hasKeyOrPut*[A, B](t: var Table[A, B], key: A, val: B): bool =
- ## Returns true if `key` is in the table, otherwise inserts `value`.
- ##
- ## See also:
- ## * `hasKey proc<#hasKey,Table[A,B],A>`_
- ## * `[] proc<#[],Table[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.toTable
- if a.hasKeyOrPut('a', 50):
- a['a'] = 99
- if a.hasKeyOrPut('z', 50):
- a['z'] = 99
- doAssert a == {'a': 99, 'b': 9, 'z': 50}.toTable
- hasKeyOrPutImpl(enlarge)
- proc getOrDefault*[A, B](t: Table[A, B], key: A): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
- ## default initialization value for type `B` is returned (e.g. 0 for any
- ## integer type).
- ##
- ## See also:
- ## * `[] proc<#[],Table[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,Table[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,Table[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,Table[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toTable
- doAssert a.getOrDefault('a') == 5
- doAssert a.getOrDefault('z') == 0
- result = default(B)
- getOrDefaultImpl(t, key)
- proc getOrDefault*[A, B](t: Table[A, B], key: A, default: B): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`.
- ## Otherwise, `default` is returned.
- ##
- ## See also:
- ## * `[] proc<#[],Table[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,Table[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,Table[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,Table[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toTable
- doAssert a.getOrDefault('a', 99) == 5
- doAssert a.getOrDefault('z', 99) == 99
- result = default(B)
- getOrDefaultImpl(t, key, default)
- proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
- ## Retrieves value at `t[key]` or puts `val` if not present, either way
- ## returning a value which can be modified.
- ##
- ##
- ## Note that while the value returned is of type `var B`,
- ## it is easy to accidentally create a copy of the value at `t[key]`.
- ## Remember that seqs and strings are value types, and therefore
- ## cannot be copied into a separate variable for modification.
- ## See the example below.
- ##
- ## See also:
- ## * `[] proc<#[],Table[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,Table[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,Table[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,Table[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.toTable
- doAssert a.mgetOrPut('a', 99) == 5
- doAssert a.mgetOrPut('z', 99) == 99
- doAssert a == {'a': 5, 'b': 9, 'z': 99}.toTable
- # An example of accidentally creating a copy
- var t = initTable[int, seq[int]]()
- # In this example, we expect t[10] to be modified,
- # but it is not.
- var copiedSeq = t.mgetOrPut(10, @[10])
- copiedSeq.add(20)
- doAssert t[10] == @[10]
- # Correct
- t.mgetOrPut(25, @[25]).add(35)
- doAssert t[25] == @[25, 35]
- mgetOrPutImpl(enlarge)
- proc mgetOrPut*[A, B](t: var Table[A, B], key: A): var B =
- ## Retrieves the value at `t[key]` or puts the
- ## default initialization value for type `B` (e.g. 0 for any
- ## integer type).
- runnableExamples:
- var a = {'a': 5}.newTable
- doAssert a.mgetOrPut('a') == 5
- a.mgetOrPut('z').inc
- doAssert a == {'a': 5, 'z': 1}.newTable
- mgetOrPutImpl(enlarge)
- proc len*[A, B](t: Table[A, B]): int =
- ## Returns the number of keys in `t`.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toTable
- doAssert len(a) == 2
- result = t.counter
- proc add*[A, B](t: var Table[A, B], key: A, val: sink B) {.deprecated:
- "Deprecated since v1.4; it was more confusing than useful, use `[]=`".} =
- ## Puts a new `(key, value)` pair into `t` even if `t[key]` already exists.
- ##
- ## **This can introduce duplicate keys into the table!**
- ##
- ## Use `[]= proc<#[]=,Table[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table without introducing duplicates.
- addImpl(enlarge)
- template tabMakeEmpty(i) = t.data[i].hcode = 0
- template tabCellEmpty(i) = isEmpty(t.data[i].hcode)
- template tabCellHash(i) = t.data[i].hcode
- proc del*[A, B](t: var Table[A, B], key: A) =
- ## Deletes `key` from hash table `t`. Does nothing if the key does not exist.
- ##
- ## .. warning:: If duplicate keys were added (via the now deprecated `add` proc),
- ## this may need to be called multiple times.
- ##
- ## See also:
- ## * `pop proc<#pop,Table[A,B],A,B>`_
- ## * `clear proc<#clear,Table[A,B]>`_ to empty the whole table
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.toTable
- a.del('a')
- doAssert a == {'b': 9, 'c': 13}.toTable
- a.del('z')
- doAssert a == {'b': 9, 'c': 13}.toTable
- delImpl(tabMakeEmpty, tabCellEmpty, tabCellHash)
- proc pop*[A, B](t: var Table[A, B], key: A, val: var B): bool =
- ## Deletes the `key` from the table.
- ## Returns `true`, if the `key` existed, and sets `val` to the
- ## mapping of the key. Otherwise, returns `false`, and the `val` is
- ## unchanged.
- ##
- ## .. warning:: If duplicate keys were added (via the now deprecated `add` proc),
- ## this may need to be called multiple times.
- ##
- ## See also:
- ## * `del proc<#del,Table[A,B],A>`_
- ## * `clear proc<#clear,Table[A,B]>`_ to empty the whole table
- runnableExamples:
- var
- a = {'a': 5, 'b': 9, 'c': 13}.toTable
- i: int
- doAssert a.pop('b', i) == true
- doAssert a == {'a': 5, 'c': 13}.toTable
- doAssert i == 9
- i = 0
- doAssert a.pop('z', i) == false
- doAssert a == {'a': 5, 'c': 13}.toTable
- doAssert i == 0
- var hc: Hash
- var index = rawGet(t, key, hc)
- result = index >= 0
- if result:
- val = move(t.data[index].val)
- delImplIdx(t, index, tabMakeEmpty, tabCellEmpty, tabCellHash)
- proc take*[A, B](t: var Table[A, B], key: A, val: var B): bool {.inline.} =
- ## Alias for:
- ## * `pop proc<#pop,Table[A,B],A,B>`_
- pop(t, key, val)
- proc clear*[A, B](t: var Table[A, B]) =
- ## Resets the table so that it is empty.
- ##
- ## See also:
- ## * `del proc<#del,Table[A,B],A>`_
- ## * `pop proc<#pop,Table[A,B],A,B>`_
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.toTable
- doAssert len(a) == 3
- clear(a)
- doAssert len(a) == 0
- clearImpl()
- proc `$`*[A, B](t: Table[A, B]): string =
- ## The `$` operator for hash tables. Used internally when calling `echo`
- ## on a table.
- dollarImpl()
- proc `==`*[A, B](s, t: Table[A, B]): bool =
- ## The `==` operator for hash tables. Returns `true` if the content of both
- ## tables contains the same key-value pairs. Insert order does not matter.
- runnableExamples:
- let
- a = {'a': 5, 'b': 9, 'c': 13}.toTable
- b = {'b': 9, 'c': 13, 'a': 5}.toTable
- doAssert a == b
- equalsImpl(s, t)
- proc indexBy*[A, B, C](collection: A, index: proc(x: B): C): Table[C, B] =
- ## Index the collection with the proc provided.
- # TODO: As soon as supported, change collection: A to collection: A[B]
- result = initTable[C, B]()
- for item in collection:
- result[index(item)] = item
- template withValue*[A, B](t: var Table[A, B], key: A, value, body: untyped) =
- ## Retrieves the value at `t[key]`.
- ##
- ## `value` can be modified in the scope of the `withValue` call.
- runnableExamples:
- type
- User = object
- name: string
- uid: int
- var t = initTable[int, User]()
- let u = User(name: "Hello", uid: 99)
- t[1] = u
- t.withValue(1, value):
- # block is executed only if `key` in `t`
- value.name = "Nim"
- value.uid = 1314
- t.withValue(2, value):
- value.name = "No"
- value.uid = 521
- assert t[1].name == "Nim"
- assert t[1].uid == 1314
- mixin rawGet
- var hc: Hash
- var index = rawGet(t, key, hc)
- let hasKey = index >= 0
- if hasKey:
- var value {.inject.} = addr(t.data[index].val)
- body
- template withValue*[A, B](t: var Table[A, B], key: A,
- value, body1, body2: untyped) =
- ## Retrieves the value at `t[key]`.
- ##
- ## `value` can be modified in the scope of the `withValue` call.
- runnableExamples:
- type
- User = object
- name: string
- uid: int
- var t = initTable[int, User]()
- let u = User(name: "Hello", uid: 99)
- t[1] = u
- t.withValue(1, value):
- # block is executed only if `key` in `t`
- value.name = "Nim"
- value.uid = 1314
- t.withValue(521, value):
- doAssert false
- do:
- # block is executed when `key` not in `t`
- t[1314] = User(name: "exist", uid: 521)
- assert t[1].name == "Nim"
- assert t[1].uid == 1314
- assert t[1314].name == "exist"
- assert t[1314].uid == 521
- mixin rawGet
- var hc: Hash
- var index = rawGet(t, key, hc)
- let hasKey = index >= 0
- if hasKey:
- var value {.inject.} = addr(t.data[index].val)
- body1
- else:
- body2
- iterator pairs*[A, B](t: Table[A, B]): (A, B) =
- ## Iterates over any `(key, value)` pair in the table `t`.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,Table[A,B]>`_
- ## * `keys iterator<#keys.i,Table[A,B]>`_
- ## * `values iterator<#values.i,Table[A,B]>`_
- ##
- ## **Examples:**
- ##
- ## ```Nim
- ## let a = {
- ## 'o': [1, 5, 7, 9],
- ## 'e': [2, 4, 6, 8]
- ## }.toTable
- ##
- ## for k, v in a.pairs:
- ## echo "key: ", k
- ## echo "value: ", v
- ##
- ## # key: e
- ## # value: [2, 4, 6, 8]
- ## # key: o
- ## # value: [1, 5, 7, 9]
- ## ```
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mpairs*[A, B](t: var Table[A, B]): (A, var B) =
- ## Iterates over any `(key, value)` pair in the table `t` (must be
- ## declared as `var`). The values can be modified.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,Table[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,Table[A,B]>`_
- runnableExamples:
- var a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toTable
- for k, v in a.mpairs:
- v.add(v[0] + 10)
- doAssert a == {'e': @[2, 4, 6, 8, 12], 'o': @[1, 5, 7, 9, 11]}.toTable
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator keys*[A, B](t: Table[A, B]): lent A =
- ## Iterates over any key in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,Table[A,B]>`_
- ## * `values iterator<#values.i,Table[A,B]>`_
- runnableExamples:
- var a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toTable
- for k in a.keys:
- a[k].add(99)
- doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.toTable
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield t.data[h].key
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator values*[A, B](t: Table[A, B]): lent B =
- ## Iterates over any value in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,Table[A,B]>`_
- ## * `keys iterator<#keys.i,Table[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,Table[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toTable
- for v in a.values:
- doAssert v.len == 4
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mvalues*[A, B](t: var Table[A, B]): var B =
- ## Iterates over any value in the table `t` (must be
- ## declared as `var`). The values can be modified.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,Table[A,B]>`_
- ## * `values iterator<#values.i,Table[A,B]>`_
- runnableExamples:
- var a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toTable
- for v in a.mvalues:
- v.add(99)
- doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.toTable
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator allValues*[A, B](t: Table[A, B]; key: A): B {.deprecated:
- "Deprecated since v1.4; tables with duplicated keys are deprecated".} =
- ## Iterates over any value in the table `t` that belongs to the given `key`.
- ##
- ## Used if you have a table with duplicate keys (as a result of using
- ## `add proc<#add,Table[A,B],A,sinkB>`_).
- ##
- runnableExamples:
- import std/[sequtils, algorithm]
- var a = {'a': 3, 'b': 5}.toTable
- for i in 1..3: a.add('z', 10*i)
- doAssert toSeq(a.pairs).sorted == @[('a', 3), ('b', 5), ('z', 10), ('z', 20), ('z', 30)]
- doAssert sorted(toSeq(a.allValues('z'))) == @[10, 20, 30]
- var h: Hash = genHash(key) and high(t.data)
- let L = len(t)
- while isFilled(t.data[h].hcode):
- if t.data[h].key == key:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- h = nextTry(h, high(t.data))
- # -------------------------------------------------------------------
- # ---------------------------- TableRef -----------------------------
- # -------------------------------------------------------------------
- proc newTable*[A, B](initialSize = defaultInitialSize): TableRef[A, B] =
- ## Creates a new ref hash table that is empty.
- ##
- ## See also:
- ## * `newTable proc<#newTable,openArray[]>`_ for creating a `TableRef`
- ## from a collection of `(key, value)` pairs
- ## * `initTable proc<#initTable>`_ for creating a `Table`
- runnableExamples:
- let
- a = newTable[int, string]()
- b = newTable[char, seq[int]]()
- new(result)
- {.noSideEffect.}:
- result[] = initTable[A, B](initialSize)
- proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] =
- ## Creates a new ref hash table that contains the given `pairs`.
- ##
- ## `pairs` is a container consisting of `(key, value)` tuples.
- ##
- ## See also:
- ## * `newTable proc<#newTable>`_
- ## * `toTable proc<#toTable,openArray[]>`_ for a `Table` version
- runnableExamples:
- let a = [('a', 5), ('b', 9)]
- let b = newTable(a)
- assert b == {'a': 5, 'b': 9}.newTable
- new(result)
- {.noSideEffect.}:
- result[] = toTable[A, B](pairs)
- proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] =
- ## Index the collection with the proc provided.
- # TODO: As soon as supported, change collection: A to collection: A[B]
- result = newTable[C, B]()
- {.noSideEffect.}:
- for item in collection:
- result[index(item)] = item
- proc `[]`*[A, B](t: TableRef[A, B], key: A): var B =
- ## Retrieves the value at `t[key]`.
- ##
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- ## One can check with `hasKey proc<#hasKey,TableRef[A,B],A>`_ whether
- ## the key exists.
- ##
- ## See also:
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]=,TableRef[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,TableRef[A,B],A>`_ for checking if a key is in
- ## the table
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newTable
- doAssert a['a'] == 5
- doAssertRaises(KeyError):
- echo a['z']
- result = t[][key]
- proc `[]=`*[A, B](t: TableRef[A, B], key: A, val: sink B) =
- ## Inserts a `(key, value)` pair into `t`.
- ##
- ## See also:
- ## * `[] proc<#[],TableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKeyOrPut proc<#hasKeyOrPut,TableRef[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,TableRef[A,B],A,B>`_
- ## * `del proc<#del,TableRef[A,B],A>`_ for removing a key from the table
- runnableExamples:
- var a = newTable[char, int]()
- a['x'] = 7
- a['y'] = 33
- doAssert a == {'x': 7, 'y': 33}.newTable
- t[][key] = val
- proc hasKey*[A, B](t: TableRef[A, B], key: A): bool =
- ## Returns true if `key` is in the table `t`.
- ##
- ## See also:
- ## * `contains proc<#contains,TableRef[A,B],A>`_ for use with the `in`
- ## operator
- ## * `[] proc<#[],TableRef[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newTable
- doAssert a.hasKey('a') == true
- doAssert a.hasKey('z') == false
- result = t[].hasKey(key)
- proc contains*[A, B](t: TableRef[A, B], key: A): bool =
- ## Alias of `hasKey proc<#hasKey,TableRef[A,B],A>`_ for use with
- ## the `in` operator.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newTable
- doAssert 'b' in a == true
- doAssert a.contains('z') == false
- return hasKey[A, B](t, key)
- proc hasKeyOrPut*[A, B](t: TableRef[A, B], key: A, val: B): bool =
- ## Returns true if `key` is in the table, otherwise inserts `value`.
- ##
- ## See also:
- ## * `hasKey proc<#hasKey,TableRef[A,B],A>`_
- ## * `[] proc<#[],TableRef[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.newTable
- if a.hasKeyOrPut('a', 50):
- a['a'] = 99
- if a.hasKeyOrPut('z', 50):
- a['z'] = 99
- doAssert a == {'a': 99, 'b': 9, 'z': 50}.newTable
- t[].hasKeyOrPut(key, val)
- proc getOrDefault*[A, B](t: TableRef[A, B], key: A): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
- ## default initialization value for type `B` is returned (e.g. 0 for any
- ## integer type).
- ##
- ## See also:
- ## * `[] proc<#[],TableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,TableRef[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,TableRef[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,TableRef[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newTable
- doAssert a.getOrDefault('a') == 5
- doAssert a.getOrDefault('z') == 0
- getOrDefault(t[], key)
- proc getOrDefault*[A, B](t: TableRef[A, B], key: A, default: B): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`.
- ## Otherwise, `default` is returned.
- ##
- ## See also:
- ## * `[] proc<#[],TableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,TableRef[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,TableRef[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,TableRef[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newTable
- doAssert a.getOrDefault('a', 99) == 5
- doAssert a.getOrDefault('z', 99) == 99
- getOrDefault(t[], key, default)
- proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
- ## Retrieves value at `t[key]` or puts `val` if not present, either way
- ## returning a value which can be modified.
- ##
- ## Note that while the value returned is of type `var B`,
- ## it is easy to accidentally create an copy of the value at `t[key]`.
- ## Remember that seqs and strings are value types, and therefore
- ## cannot be copied into a separate variable for modification.
- ## See the example below.
- ##
- ## See also:
- ## * `[] proc<#[],TableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,TableRef[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,TableRef[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,TableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.newTable
- doAssert a.mgetOrPut('a', 99) == 5
- doAssert a.mgetOrPut('z', 99) == 99
- doAssert a == {'a': 5, 'b': 9, 'z': 99}.newTable
- # An example of accidentally creating a copy
- var t = newTable[int, seq[int]]()
- # In this example, we expect t[10] to be modified,
- # but it is not.
- var copiedSeq = t.mgetOrPut(10, @[10])
- copiedSeq.add(20)
- doAssert t[10] == @[10]
- # Correct
- t.mgetOrPut(25, @[25]).add(35)
- doAssert t[25] == @[25, 35]
- t[].mgetOrPut(key, val)
- proc mgetOrPut*[A, B](t: TableRef[A, B], key: A): var B =
- ## Retrieves the value at `t[key]` or puts the
- ## default initialization value for type `B` (e.g. 0 for any
- ## integer type).
- runnableExamples:
- var a = {'a': 5}.newTable
- doAssert a.mgetOrPut('a') == 5
- a.mgetOrPut('z').inc
- doAssert a == {'a': 5, 'z': 1}.newTable
- t[].mgetOrPut(key)
- proc len*[A, B](t: TableRef[A, B]): int =
- ## Returns the number of keys in `t`.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newTable
- doAssert len(a) == 2
- result = t.counter
- proc add*[A, B](t: TableRef[A, B], key: A, val: sink B) {.deprecated:
- "Deprecated since v1.4; it was more confusing than useful, use `[]=`".} =
- ## Puts a new `(key, value)` pair into `t` even if `t[key]` already exists.
- ##
- ## **This can introduce duplicate keys into the table!**
- ##
- ## Use `[]= proc<#[]=,TableRef[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table without introducing duplicates.
- t[].add(key, val)
- proc del*[A, B](t: TableRef[A, B], key: A) =
- ## Deletes `key` from hash table `t`. Does nothing if the key does not exist.
- ##
- ## .. warning:: If duplicate keys were added (via the now deprecated `add` proc),
- ## this may need to be called multiple times.
- ##
- ## See also:
- ## * `pop proc<#pop,TableRef[A,B],A,B>`_
- ## * `clear proc<#clear,TableRef[A,B]>`_ to empty the whole table
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.newTable
- a.del('a')
- doAssert a == {'b': 9, 'c': 13}.newTable
- a.del('z')
- doAssert a == {'b': 9, 'c': 13}.newTable
- t[].del(key)
- proc pop*[A, B](t: TableRef[A, B], key: A, val: var B): bool =
- ## Deletes the `key` from the table.
- ## Returns `true`, if the `key` existed, and sets `val` to the
- ## mapping of the key. Otherwise, returns `false`, and the `val` is
- ## unchanged.
- ##
- ## .. warning:: If duplicate keys were added (via the now deprecated `add` proc),
- ## this may need to be called multiple times.
- ##
- ## See also:
- ## * `del proc<#del,TableRef[A,B],A>`_
- ## * `clear proc<#clear,TableRef[A,B]>`_ to empty the whole table
- runnableExamples:
- var
- a = {'a': 5, 'b': 9, 'c': 13}.newTable
- i: int
- doAssert a.pop('b', i) == true
- doAssert a == {'a': 5, 'c': 13}.newTable
- doAssert i == 9
- i = 0
- doAssert a.pop('z', i) == false
- doAssert a == {'a': 5, 'c': 13}.newTable
- doAssert i == 0
- result = t[].pop(key, val)
- proc take*[A, B](t: TableRef[A, B], key: A, val: var B): bool {.inline.} =
- ## Alias for:
- ## * `pop proc<#pop,TableRef[A,B],A,B>`_
- pop(t, key, val)
- proc clear*[A, B](t: TableRef[A, B]) =
- ## Resets the table so that it is empty.
- ##
- ## See also:
- ## * `del proc<#del,Table[A,B],A>`_
- ## * `pop proc<#pop,Table[A,B],A,B>`_
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.newTable
- doAssert len(a) == 3
- clear(a)
- doAssert len(a) == 0
- clearImpl()
- proc `$`*[A, B](t: TableRef[A, B]): string =
- ## The `$` operator for hash tables. Used internally when calling `echo`
- ## on a table.
- dollarImpl()
- proc `==`*[A, B](s, t: TableRef[A, B]): bool =
- ## The `==` operator for hash tables. Returns `true` if either both tables
- ## are `nil`, or neither is `nil` and the content of both tables contains the
- ## same key-value pairs. Insert order does not matter.
- runnableExamples:
- let
- a = {'a': 5, 'b': 9, 'c': 13}.newTable
- b = {'b': 9, 'c': 13, 'a': 5}.newTable
- doAssert a == b
- if isNil(s): result = isNil(t)
- elif isNil(t): result = false
- else: equalsImpl(s[], t[])
- iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
- ## Iterates over any `(key, value)` pair in the table `t`.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,TableRef[A,B]>`_
- ## * `keys iterator<#keys.i,TableRef[A,B]>`_
- ## * `values iterator<#values.i,TableRef[A,B]>`_
- ##
- ## **Examples:**
- ##
- ## ```Nim
- ## let a = {
- ## 'o': [1, 5, 7, 9],
- ## 'e': [2, 4, 6, 8]
- ## }.newTable
- ##
- ## for k, v in a.pairs:
- ## echo "key: ", k
- ## echo "value: ", v
- ##
- ## # key: e
- ## # value: [2, 4, 6, 8]
- ## # key: o
- ## # value: [1, 5, 7, 9]
- ## ```
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mpairs*[A, B](t: TableRef[A, B]): (A, var B) =
- ## Iterates over any `(key, value)` pair in the table `t`. The values
- ## can be modified.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,TableRef[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,TableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newTable
- for k, v in a.mpairs:
- v.add(v[0] + 10)
- doAssert a == {'e': @[2, 4, 6, 8, 12], 'o': @[1, 5, 7, 9, 11]}.newTable
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator keys*[A, B](t: TableRef[A, B]): lent A =
- ## Iterates over any key in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,TableRef[A,B]>`_
- ## * `values iterator<#values.i,TableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newTable
- for k in a.keys:
- a[k].add(99)
- doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.newTable
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield t.data[h].key
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator values*[A, B](t: TableRef[A, B]): lent B =
- ## Iterates over any value in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,TableRef[A,B]>`_
- ## * `keys iterator<#keys.i,TableRef[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,TableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newTable
- for v in a.values:
- doAssert v.len == 4
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mvalues*[A, B](t: TableRef[A, B]): var B =
- ## Iterates over any value in the table `t`. The values can be modified.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,TableRef[A,B]>`_
- ## * `values iterator<#values.i,TableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newTable
- for v in a.mvalues:
- v.add(99)
- doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.newTable
- let L = len(t)
- for h in 0 .. high(t.data):
- if isFilled(t.data[h].hcode):
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- # ---------------------------------------------------------------------------
- # ------------------------------ OrderedTable -------------------------------
- # ---------------------------------------------------------------------------
- type
- OrderedKeyValuePair[A, B] = tuple[
- hcode: Hash, next: int, key: A, val: B]
- OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]]
- OrderedTable*[A, B] = object
- ## Hash table that remembers insertion order.
- ##
- ## For creating an empty OrderedTable, use `initOrderedTable proc
- ## <#initOrderedTable>`_.
- data: OrderedKeyValuePairSeq[A, B]
- counter, first, last: int
- OrderedTableRef*[A, B] = ref OrderedTable[A, B] ## Ref version of
- ## `OrderedTable<#OrderedTable>`_.
- ##
- ## For creating a new empty OrderedTableRef, use `newOrderedTable proc
- ## <#newOrderedTable>`_.
- # ------------------------------ helpers ---------------------------------
- proc rawGetKnownHC[A, B](t: OrderedTable[A, B], key: A, hc: Hash): int =
- rawGetKnownHCImpl()
- proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int {.inline.} =
- rawGetDeepImpl()
- proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int =
- rawGetImpl()
- proc rawInsert[A, B](t: var OrderedTable[A, B],
- data: var OrderedKeyValuePairSeq[A, B],
- key: A, val: sink B, hc: Hash, h: Hash) =
- rawInsertImpl()
- data[h].next = -1
- if t.first < 0: t.first = h
- if t.last >= 0: data[t.last].next = h
- t.last = h
- proc enlarge[A, B](t: var OrderedTable[A, B]) =
- var n: OrderedKeyValuePairSeq[A, B]
- newSeq(n, len(t.data) * growthFactor)
- var h = t.first
- t.first = -1
- t.last = -1
- swap(t.data, n)
- while h >= 0:
- var nxt = n[h].next
- let eh = n[h].hcode
- if isFilled(eh):
- var j: Hash = eh and maxHash(t)
- while isFilled(t.data[j].hcode):
- j = nextTry(j, maxHash(t))
- rawInsert(t, t.data, move n[h].key, move n[h].val, n[h].hcode, j)
- h = nxt
- template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
- if t.counter > 0:
- var h = t.first
- while h >= 0:
- var nxt = t.data[h].next
- if isFilled(t.data[h].hcode):
- yieldStmt
- h = nxt
- # ----------------------------------------------------------------------
- proc initOrderedTable*[A, B](initialSize = defaultInitialSize): OrderedTable[A, B] =
- ## Creates a new ordered hash table that is empty.
- ##
- ## Starting from Nim v0.20, tables are initialized by default and it is
- ## not necessary to call this function explicitly.
- ##
- ## See also:
- ## * `toOrderedTable proc<#toOrderedTable,openArray[]>`_
- ## * `newOrderedTable proc<#newOrderedTable>`_ for creating an
- ## `OrderedTableRef`
- runnableExamples:
- let
- a = initOrderedTable[int, string]()
- b = initOrderedTable[char, seq[int]]()
- result = default(OrderedTable[A, B])
- initImpl(result, initialSize)
- proc `[]=`*[A, B](t: var OrderedTable[A, B], key: A, val: sink B) =
- ## Inserts a `(key, value)` pair into `t`.
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTable[A,B],A>`_ for retrieving a value of a key
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTable[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,OrderedTable[A,B],A,B>`_
- ## * `del proc<#del,OrderedTable[A,B],A>`_ for removing a key from the table
- runnableExamples:
- var a = initOrderedTable[char, int]()
- a['x'] = 7
- a['y'] = 33
- doAssert a == {'x': 7, 'y': 33}.toOrderedTable
- putImpl(enlarge)
- proc toOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTable[A, B] =
- ## Creates a new ordered hash table that contains the given `pairs`.
- ##
- ## `pairs` is a container consisting of `(key, value)` tuples.
- ##
- ## See also:
- ## * `initOrderedTable proc<#initOrderedTable>`_
- ## * `newOrderedTable proc<#newOrderedTable,openArray[]>`_ for an
- ## `OrderedTableRef` version
- runnableExamples:
- let a = [('a', 5), ('b', 9)]
- let b = toOrderedTable(a)
- assert b == {'a': 5, 'b': 9}.toOrderedTable
- result = initOrderedTable[A, B](pairs.len)
- for key, val in items(pairs): result[key] = val
- proc `[]`*[A, B](t: OrderedTable[A, B], key: A): lent B =
- ## Retrieves the value at `t[key]`.
- ##
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- ## One can check with `hasKey proc<#hasKey,OrderedTable[A,B],A>`_ whether
- ## the key exists.
- ##
- ## See also:
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]=,OrderedTable[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,OrderedTable[A,B],A>`_ for checking if a
- ## key is in the table
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert a['a'] == 5
- doAssertRaises(KeyError):
- echo a['z']
- get(t, key)
- proc `[]`*[A, B](t: var OrderedTable[A, B], key: A): var B =
- ## Retrieves the value at `t[key]`. The value can be modified.
- ##
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- ##
- ## See also:
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]=,OrderedTable[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,OrderedTable[A,B],A>`_ for checking if a
- ## key is in the table
- get(t, key)
- proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
- ## Returns true if `key` is in the table `t`.
- ##
- ## See also:
- ## * `contains proc<#contains,OrderedTable[A,B],A>`_ for use with the `in`
- ## operator
- ## * `[] proc<#[],OrderedTable[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert a.hasKey('a') == true
- doAssert a.hasKey('z') == false
- var hc: Hash = default(Hash)
- result = rawGet(t, key, hc) >= 0
- proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =
- ## Alias of `hasKey proc<#hasKey,OrderedTable[A,B],A>`_ for use with
- ## the `in` operator.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert 'b' in a == true
- doAssert a.contains('z') == false
- return hasKey[A, B](t, key)
- proc hasKeyOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): bool =
- ## Returns true if `key` is in the table, otherwise inserts `value`.
- ##
- ## See also:
- ## * `hasKey proc<#hasKey,OrderedTable[A,B],A>`_
- ## * `[] proc<#[],OrderedTable[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.toOrderedTable
- if a.hasKeyOrPut('a', 50):
- a['a'] = 99
- if a.hasKeyOrPut('z', 50):
- a['z'] = 99
- doAssert a == {'a': 99, 'b': 9, 'z': 50}.toOrderedTable
- hasKeyOrPutImpl(enlarge)
- proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
- ## default initialization value for type `B` is returned (e.g. 0 for any
- ## integer type).
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTable[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,OrderedTable[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTable[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,OrderedTable[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert a.getOrDefault('a') == 5
- doAssert a.getOrDefault('z') == 0
- result = default(B)
- getOrDefaultImpl(t, key)
- proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A, default: B): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`.
- ## Otherwise, `default` is returned.
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTable[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,OrderedTable[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTable[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,OrderedTable[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert a.getOrDefault('a', 99) == 5
- doAssert a.getOrDefault('z', 99) == 99
- result = default(B)
- getOrDefaultImpl(t, key, default)
- proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
- ## Retrieves value at `t[key]` or puts `val` if not present, either way
- ## returning a value which can be modified.
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTable[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,OrderedTable[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTable[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTable[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert a.mgetOrPut('a', 99) == 5
- doAssert a.mgetOrPut('z', 99) == 99
- doAssert a == {'a': 5, 'b': 9, 'z': 99}.toOrderedTable
- mgetOrPutImpl(enlarge)
- proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A): var B =
- ## Retrieves the value at `t[key]` or puts the
- ## default initialization value for type `B` (e.g. 0 for any
- ## integer type).
- runnableExamples:
- var a = {'a': 5}.toOrderedTable
- doAssert a.mgetOrPut('a') == 5
- a.mgetOrPut('z').inc
- doAssert a == {'a': 5, 'z': 1}.toOrderedTable
- mgetOrPutImpl(enlarge)
- proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} =
- ## Returns the number of keys in `t`.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.toOrderedTable
- doAssert len(a) == 2
- result = t.counter
- proc add*[A, B](t: var OrderedTable[A, B], key: A, val: sink B) {.deprecated:
- "Deprecated since v1.4; it was more confusing than useful, use `[]=`".} =
- ## Puts a new `(key, value)` pair into `t` even if `t[key]` already exists.
- ##
- ## **This can introduce duplicate keys into the table!**
- ##
- ## Use `[]= proc<#[]=,OrderedTable[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table without introducing duplicates.
- addImpl(enlarge)
- proc del*[A, B](t: var OrderedTable[A, B], key: A) =
- ## Deletes `key` from hash table `t`. Does nothing if the key does not exist.
- ##
- ## O(n) complexity.
- ##
- ## See also:
- ## * `pop proc<#pop,OrderedTable[A,B],A,B>`_
- ## * `clear proc<#clear,OrderedTable[A,B]>`_ to empty the whole table
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.toOrderedTable
- a.del('a')
- doAssert a == {'b': 9, 'c': 13}.toOrderedTable
- a.del('z')
- doAssert a == {'b': 9, 'c': 13}.toOrderedTable
- if t.counter == 0: return
- var n: OrderedKeyValuePairSeq[A, B]
- newSeq(n, len(t.data))
- var h = t.first
- t.first = -1
- t.last = -1
- swap(t.data, n)
- let hc = genHash(key)
- while h >= 0:
- var nxt = n[h].next
- if isFilled(n[h].hcode):
- if n[h].hcode == hc and n[h].key == key:
- dec t.counter
- else:
- var j = -1 - rawGetKnownHC(t, n[h].key, n[h].hcode)
- rawInsert(t, t.data, move n[h].key, move n[h].val, n[h].hcode, j)
- h = nxt
- proc pop*[A, B](t: var OrderedTable[A, B], key: A, val: var B): bool {.since: (1, 1).} =
- ## Deletes the `key` from the table.
- ## Returns `true`, if the `key` existed, and sets `val` to the
- ## mapping of the key. Otherwise, returns `false`, and the `val` is
- ## unchanged.
- ##
- ## O(n) complexity.
- ##
- ## See also:
- ## * `del proc<#del,OrderedTable[A,B],A>`_
- ## * `clear proc<#clear,OrderedTable[A,B]>`_ to empty the whole table
- runnableExamples:
- var
- a = {'c': 5, 'b': 9, 'a': 13}.toOrderedTable
- i: int
- doAssert a.pop('b', i) == true
- doAssert a == {'c': 5, 'a': 13}.toOrderedTable
- doAssert i == 9
- i = 0
- doAssert a.pop('z', i) == false
- doAssert a == {'c': 5, 'a': 13}.toOrderedTable
- doAssert i == 0
- var hc: Hash
- var index = rawGet(t, key, hc)
- result = index >= 0
- if result:
- val = move(t.data[index].val)
- del(t, key)
- proc clear*[A, B](t: var OrderedTable[A, B]) =
- ## Resets the table so that it is empty.
- ##
- ## See also:
- ## * `del proc<#del,OrderedTable[A,B],A>`_
- ## * `pop proc<#pop,OrderedTable[A,B],A,B>`_
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.toOrderedTable
- doAssert len(a) == 3
- clear(a)
- doAssert len(a) == 0
- clearImpl()
- t.first = -1
- t.last = -1
- proc sort*[A, B](t: var OrderedTable[A, B], cmp: proc (x, y: (A, B)): int,
- order = SortOrder.Ascending) {.effectsOf: cmp.} =
- ## Sorts `t` according to the function `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 proc<#sort,CountTable[A]>`_ for count tables).
- runnableExamples:
- import std/[algorithm]
- var a = initOrderedTable[char, int]()
- for i, c in "cab":
- a[c] = 10*i
- doAssert a == {'c': 0, 'a': 10, 'b': 20}.toOrderedTable
- a.sort(system.cmp)
- doAssert a == {'a': 10, 'b': 20, 'c': 0}.toOrderedTable
- a.sort(system.cmp, order = SortOrder.Descending)
- doAssert a == {'c': 0, 'b': 20, 'a': 10}.toOrderedTable
- 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)) * order <= 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
- proc `$`*[A, B](t: OrderedTable[A, B]): string =
- ## The `$` operator for ordered hash tables. Used internally when calling
- ## `echo` on a table.
- dollarImpl()
- proc `==`*[A, B](s, t: OrderedTable[A, B]): bool =
- ## The `==` operator for ordered hash tables. Returns `true` if both the
- ## content and the order are equal.
- runnableExamples:
- let
- a = {'a': 5, 'b': 9, 'c': 13}.toOrderedTable
- b = {'b': 9, 'c': 13, 'a': 5}.toOrderedTable
- doAssert a != b
- if s.counter != t.counter:
- return false
- if s.counter == 0 and t.counter == 0:
- return true
- var ht = t.first
- var hs = s.first
- while ht >= 0 and hs >= 0:
- var nxtt = t.data[ht].next
- var nxts = s.data[hs].next
- if isFilled(t.data[ht].hcode) and isFilled(s.data[hs].hcode):
- if (s.data[hs].key != t.data[ht].key) or (s.data[hs].val != t.data[ht].val):
- return false
- ht = nxtt
- hs = nxts
- return true
- iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
- ## Iterates over any `(key, value)` pair in the table `t` in insertion
- ## order.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,OrderedTable[A,B]>`_
- ## * `keys iterator<#keys.i,OrderedTable[A,B]>`_
- ## * `values iterator<#values.i,OrderedTable[A,B]>`_
- ##
- ## **Examples:**
- ##
- ## ```Nim
- ## let a = {
- ## 'o': [1, 5, 7, 9],
- ## 'e': [2, 4, 6, 8]
- ## }.toOrderedTable
- ##
- ## for k, v in a.pairs:
- ## echo "key: ", k
- ## echo "value: ", v
- ##
- ## # key: o
- ## # value: [1, 5, 7, 9]
- ## # key: e
- ## # value: [2, 4, 6, 8]
- ## ```
- let L = len(t)
- forAllOrderedPairs:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mpairs*[A, B](t: var OrderedTable[A, B]): (A, var B) =
- ## Iterates over any `(key, value)` pair in the table `t` (must be
- ## declared as `var`) in insertion order. The values can be modified.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,OrderedTable[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,OrderedTable[A,B]>`_
- runnableExamples:
- var a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toOrderedTable
- for k, v in a.mpairs:
- v.add(v[0] + 10)
- doAssert a == {'o': @[1, 5, 7, 9, 11],
- 'e': @[2, 4, 6, 8, 12]}.toOrderedTable
- let L = len(t)
- forAllOrderedPairs:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator keys*[A, B](t: OrderedTable[A, B]): lent A =
- ## Iterates over any key in the table `t` in insertion order.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,OrderedTable[A,B]>`_
- ## * `values iterator<#values.i,OrderedTable[A,B]>`_
- runnableExamples:
- var a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toOrderedTable
- for k in a.keys:
- a[k].add(99)
- doAssert a == {'o': @[1, 5, 7, 9, 99],
- 'e': @[2, 4, 6, 8, 99]}.toOrderedTable
- let L = len(t)
- forAllOrderedPairs:
- yield t.data[h].key
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator values*[A, B](t: OrderedTable[A, B]): lent B =
- ## Iterates over any value in the table `t` in insertion order.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,OrderedTable[A,B]>`_
- ## * `keys iterator<#keys.i,OrderedTable[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,OrderedTable[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toOrderedTable
- for v in a.values:
- doAssert v.len == 4
- let L = len(t)
- forAllOrderedPairs:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mvalues*[A, B](t: var OrderedTable[A, B]): var B =
- ## Iterates over any value in the table `t` (must be
- ## declared as `var`) in insertion order. The values
- ## can be modified.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,OrderedTable[A,B]>`_
- ## * `values iterator<#values.i,OrderedTable[A,B]>`_
- runnableExamples:
- var a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.toOrderedTable
- for v in a.mvalues:
- v.add(99)
- doAssert a == {'o': @[1, 5, 7, 9, 99],
- 'e': @[2, 4, 6, 8, 99]}.toOrderedTable
- let L = len(t)
- forAllOrderedPairs:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- # ---------------------------------------------------------------------------
- # --------------------------- OrderedTableRef -------------------------------
- # ---------------------------------------------------------------------------
- proc newOrderedTable*[A, B](initialSize = defaultInitialSize): OrderedTableRef[A, B] =
- ## Creates a new ordered ref hash table that is empty.
- ##
- ## See also:
- ## * `newOrderedTable proc<#newOrderedTable,openArray[]>`_ for creating
- ## an `OrderedTableRef` from a collection of `(key, value)` pairs
- ## * `initOrderedTable proc<#initOrderedTable>`_ for creating an
- ## `OrderedTable`
- runnableExamples:
- let
- a = newOrderedTable[int, string]()
- b = newOrderedTable[char, seq[int]]()
- new(result)
- {.noSideEffect.}:
- result[] = initOrderedTable[A, B](initialSize)
- proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] =
- ## Creates a new ordered ref hash table that contains the given `pairs`.
- ##
- ## `pairs` is a container consisting of `(key, value)` tuples.
- ##
- ## See also:
- ## * `newOrderedTable proc<#newOrderedTable>`_
- ## * `toOrderedTable proc<#toOrderedTable,openArray[]>`_ for an
- ## `OrderedTable` version
- runnableExamples:
- let a = [('a', 5), ('b', 9)]
- let b = newOrderedTable(a)
- assert b == {'a': 5, 'b': 9}.newOrderedTable
- result = newOrderedTable[A, B](pairs.len)
- {.noSideEffect.}:
- for key, val in items(pairs): result[key] = val
- proc `[]`*[A, B](t: OrderedTableRef[A, B], key: A): var B =
- ## Retrieves the value at `t[key]`.
- ##
- ## If `key` is not in `t`, the `KeyError` exception is raised.
- ## One can check with `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_ whether
- ## the key exists.
- ##
- ## See also:
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]=,OrderedTableRef[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_ for checking if
- ## a key is in the table
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert a['a'] == 5
- doAssertRaises(KeyError):
- echo a['z']
- result = t[][key]
- proc `[]=`*[A, B](t: OrderedTableRef[A, B], key: A, val: sink B) =
- ## Inserts a `(key, value)` pair into `t`.
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `del proc<#del,OrderedTableRef[A,B],A>`_ for removing a key from the table
- runnableExamples:
- var a = newOrderedTable[char, int]()
- a['x'] = 7
- a['y'] = 33
- doAssert a == {'x': 7, 'y': 33}.newOrderedTable
- t[][key] = val
- proc hasKey*[A, B](t: OrderedTableRef[A, B], key: A): bool =
- ## Returns true if `key` is in the table `t`.
- ##
- ## See also:
- ## * `contains proc<#contains,OrderedTableRef[A,B],A>`_ for use with the `in`
- ## operator
- ## * `[] proc<#[],OrderedTableRef[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert a.hasKey('a') == true
- doAssert a.hasKey('z') == false
- result = t[].hasKey(key)
- proc contains*[A, B](t: OrderedTableRef[A, B], key: A): bool =
- ## Alias of `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_ for use with
- ## the `in` operator.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert 'b' in a == true
- doAssert a.contains('z') == false
- return hasKey[A, B](t, key)
- proc hasKeyOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): bool =
- ## Returns true if `key` is in the table, otherwise inserts `value`.
- ##
- ## See also:
- ## * `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_
- ## * `[] proc<#[],OrderedTableRef[A,B],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.newOrderedTable
- if a.hasKeyOrPut('a', 50):
- a['a'] = 99
- if a.hasKeyOrPut('z', 50):
- a['z'] = 99
- doAssert a == {'a': 99, 'b': 9, 'z': 50}.newOrderedTable
- result = t[].hasKeyOrPut(key, val)
- proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
- ## default initialization value for type `B` is returned (e.g. 0 for any
- ## integer type).
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert a.getOrDefault('a') == 5
- doAssert a.getOrDefault('z') == 0
- getOrDefault(t[], key)
- proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A, default: B): B =
- ## Retrieves the value at `t[key]` if `key` is in `t`.
- ## Otherwise, `default` is returned.
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `mgetOrPut proc<#mgetOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert a.getOrDefault('a', 99) == 5
- doAssert a.getOrDefault('z', 99) == 99
- getOrDefault(t[], key, default)
- proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
- ## Retrieves value at `t[key]` or puts `val` if not present, either way
- ## returning a value which can be modified.
- ##
- ## See also:
- ## * `[] proc<#[],OrderedTableRef[A,B],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,OrderedTableRef[A,B],A>`_
- ## * `hasKeyOrPut proc<#hasKeyOrPut,OrderedTableRef[A,B],A,B>`_
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A>`_ to return
- ## a default value (e.g. zero for int) if the key doesn't exist
- ## * `getOrDefault proc<#getOrDefault,OrderedTableRef[A,B],A,B>`_ to return
- ## a custom value if the key doesn't exist
- runnableExamples:
- var a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert a.mgetOrPut('a', 99) == 5
- doAssert a.mgetOrPut('z', 99) == 99
- doAssert a == {'a': 5, 'b': 9, 'z': 99}.newOrderedTable
- result = t[].mgetOrPut(key, val)
- proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A): var B =
- ## Retrieves the value at `t[key]` or puts the
- ## default initialization value for type `B` (e.g. 0 for any
- ## integer type).
- runnableExamples:
- var a = {'a': 5}.toOrderedTable
- doAssert a.mgetOrPut('a') == 5
- a.mgetOrPut('z').inc
- doAssert a == {'a': 5, 'z': 1}.toOrderedTable
- t[].mgetOrPut(key)
- proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} =
- ## Returns the number of keys in `t`.
- runnableExamples:
- let a = {'a': 5, 'b': 9}.newOrderedTable
- doAssert len(a) == 2
- result = t.counter
- proc add*[A, B](t: OrderedTableRef[A, B], key: A, val: sink B) {.deprecated:
- "Deprecated since v1.4; it was more confusing than useful, use `[]=`".} =
- ## Puts a new `(key, value)` pair into `t` even if `t[key]` already exists.
- ##
- ## **This can introduce duplicate keys into the table!**
- ##
- ## Use `[]= proc<#[]=,OrderedTableRef[A,B],A,sinkB>`_ for inserting a new
- ## (key, value) pair in the table without introducing duplicates.
- t[].add(key, val)
- proc del*[A, B](t: OrderedTableRef[A, B], key: A) =
- ## Deletes `key` from hash table `t`. Does nothing if the key does not exist.
- ##
- ## See also:
- ## * `clear proc<#clear,OrderedTableRef[A,B]>`_ to empty the whole table
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.newOrderedTable
- a.del('a')
- doAssert a == {'b': 9, 'c': 13}.newOrderedTable
- a.del('z')
- doAssert a == {'b': 9, 'c': 13}.newOrderedTable
- t[].del(key)
- proc pop*[A, B](t: OrderedTableRef[A, B], key: A, val: var B): bool {.since: (1, 1).} =
- ## Deletes the `key` from the table.
- ## Returns `true`, if the `key` existed, and sets `val` to the
- ## mapping of the key. Otherwise, returns `false`, and the `val` is
- ## unchanged.
- ##
- ## See also:
- ## * `del proc<#del,OrderedTableRef[A,B],A>`_
- ## * `clear proc<#clear,OrderedTableRef[A,B]>`_ to empty the whole table
- runnableExamples:
- var
- a = {'c': 5, 'b': 9, 'a': 13}.newOrderedTable
- i: int
- doAssert a.pop('b', i) == true
- doAssert a == {'c': 5, 'a': 13}.newOrderedTable
- doAssert i == 9
- i = 0
- doAssert a.pop('z', i) == false
- doAssert a == {'c': 5, 'a': 13}.newOrderedTable
- doAssert i == 0
- pop(t[], key, val)
- proc clear*[A, B](t: OrderedTableRef[A, B]) =
- ## Resets the table so that it is empty.
- ##
- ## See also:
- ## * `del proc<#del,OrderedTableRef[A,B],A>`_
- runnableExamples:
- var a = {'a': 5, 'b': 9, 'c': 13}.newOrderedTable
- doAssert len(a) == 3
- clear(a)
- doAssert len(a) == 0
- clear(t[])
- proc sort*[A, B](t: OrderedTableRef[A, B], cmp: proc (x, y: (A, B)): int,
- order = SortOrder.Ascending) {.effectsOf: cmp.} =
- ## Sorts `t` according to the function `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 proc<#sort,CountTableRef[A]>`_ for count tables).
- runnableExamples:
- import std/[algorithm]
- var a = newOrderedTable[char, int]()
- for i, c in "cab":
- a[c] = 10*i
- doAssert a == {'c': 0, 'a': 10, 'b': 20}.newOrderedTable
- a.sort(system.cmp)
- doAssert a == {'a': 10, 'b': 20, 'c': 0}.newOrderedTable
- a.sort(system.cmp, order = SortOrder.Descending)
- doAssert a == {'c': 0, 'b': 20, 'a': 10}.newOrderedTable
- t[].sort(cmp, order = order)
- proc `$`*[A, B](t: OrderedTableRef[A, B]): string =
- ## The `$` operator for hash tables. Used internally when calling `echo`
- ## on a table.
- dollarImpl()
- proc `==`*[A, B](s, t: OrderedTableRef[A, B]): bool =
- ## The `==` operator for ordered hash tables. Returns true if either both
- ## tables are `nil`, or neither is `nil` and the content and the order of
- ## both are equal.
- runnableExamples:
- let
- a = {'a': 5, 'b': 9, 'c': 13}.newOrderedTable
- b = {'b': 9, 'c': 13, 'a': 5}.newOrderedTable
- doAssert a != b
- if isNil(s): result = isNil(t)
- elif isNil(t): result = false
- else: result = s[] == t[]
- iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
- ## Iterates over any `(key, value)` pair in the table `t` in insertion
- ## order.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,OrderedTableRef[A,B]>`_
- ## * `keys iterator<#keys.i,OrderedTableRef[A,B]>`_
- ## * `values iterator<#values.i,OrderedTableRef[A,B]>`_
- ##
- ## **Examples:**
- ##
- ## ```Nim
- ## let a = {
- ## 'o': [1, 5, 7, 9],
- ## 'e': [2, 4, 6, 8]
- ## }.newOrderedTable
- ##
- ## for k, v in a.pairs:
- ## echo "key: ", k
- ## echo "value: ", v
- ##
- ## # key: o
- ## # value: [1, 5, 7, 9]
- ## # key: e
- ## # value: [2, 4, 6, 8]
- ## ```
- let L = len(t)
- forAllOrderedPairs:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mpairs*[A, B](t: OrderedTableRef[A, B]): (A, var B) =
- ## Iterates over any `(key, value)` pair in the table `t` in insertion
- ## order. The values can be modified.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,OrderedTableRef[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,OrderedTableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newOrderedTable
- for k, v in a.mpairs:
- v.add(v[0] + 10)
- doAssert a == {'o': @[1, 5, 7, 9, 11],
- 'e': @[2, 4, 6, 8, 12]}.newOrderedTable
- let L = len(t)
- forAllOrderedPairs:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator keys*[A, B](t: OrderedTableRef[A, B]): lent A =
- ## Iterates over any key in the table `t` in insertion order.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,OrderedTableRef[A,B]>`_
- ## * `values iterator<#values.i,OrderedTableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newOrderedTable
- for k in a.keys:
- a[k].add(99)
- doAssert a == {'o': @[1, 5, 7, 9, 99], 'e': @[2, 4, 6, 8,
- 99]}.newOrderedTable
- let L = len(t)
- forAllOrderedPairs:
- yield t.data[h].key
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator values*[A, B](t: OrderedTableRef[A, B]): lent B =
- ## Iterates over any value in the table `t` in insertion order.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,OrderedTableRef[A,B]>`_
- ## * `keys iterator<#keys.i,OrderedTableRef[A,B]>`_
- ## * `mvalues iterator<#mvalues.i,OrderedTableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newOrderedTable
- for v in a.values:
- doAssert v.len == 4
- let L = len(t)
- forAllOrderedPairs:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mvalues*[A, B](t: OrderedTableRef[A, B]): var B =
- ## Iterates over any value in the table `t` in insertion order. The values
- ## can be modified.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,OrderedTableRef[A,B]>`_
- ## * `values iterator<#values.i,OrderedTableRef[A,B]>`_
- runnableExamples:
- let a = {
- 'o': @[1, 5, 7, 9],
- 'e': @[2, 4, 6, 8]
- }.newOrderedTable
- for v in a.mvalues:
- v.add(99)
- doAssert a == {'o': @[1, 5, 7, 9, 99],
- 'e': @[2, 4, 6, 8, 99]}.newOrderedTable
- let L = len(t)
- forAllOrderedPairs:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- # -------------------------------------------------------------------------
- # ------------------------------ CountTable -------------------------------
- # -------------------------------------------------------------------------
- type
- CountTable*[A] = object
- ## Hash table that counts the number of each key.
- ##
- ## For creating an empty CountTable, use `initCountTable proc
- ## <#initCountTable>`_.
- data: seq[tuple[key: A, val: int]]
- counter: int
- isSorted: bool
- CountTableRef*[A] = ref CountTable[A] ## Ref version of
- ## `CountTable<#CountTable>`_.
- ##
- ## For creating a new empty CountTableRef, use `newCountTable proc
- ## <#newCountTable>`_.
- # ------------------------------ helpers ---------------------------------
- proc ctRawInsert[A](t: CountTable[A], data: var seq[tuple[key: A, val: int]],
- key: A, val: int) =
- var h: Hash = hash(key) and high(data)
- while data[h].val != 0: h = nextTry(h, high(data))
- data[h].key = key
- data[h].val = val
- proc enlarge[A](t: var CountTable[A]) =
- var n: seq[tuple[key: A, val: int]]
- newSeq(n, len(t.data) * growthFactor)
- for i in countup(0, high(t.data)):
- if t.data[i].val != 0: ctRawInsert(t, n, move t.data[i].key, move t.data[i].val)
- swap(t.data, n)
- proc rawGet[A](t: CountTable[A], key: A): int =
- if t.data.len == 0:
- return -1
- var h: Hash = hash(key) and high(t.data) # start with real hash value
- while t.data[h].val != 0:
- if t.data[h].key == key: return h
- h = nextTry(h, high(t.data))
- result = -1 - h # < 0 => MISSING; insert idx = -1 - result
- template ctget(t, key, default: untyped): untyped =
- var index = rawGet(t, key)
- result = if index >= 0: t.data[index].val else: default
- proc inc*[A](t: var CountTable[A], key: A, val = 1)
- # ----------------------------------------------------------------------
- proc initCountTable*[A](initialSize = defaultInitialSize): CountTable[A] =
- ## Creates a new count table that is empty.
- ##
- ## Starting from Nim v0.20, tables are initialized by default and it is
- ## not necessary to call this function explicitly.
- ##
- ## See also:
- ## * `toCountTable proc<#toCountTable,openArray[A]>`_
- ## * `newCountTable proc<#newCountTable>`_ for creating a
- ## `CountTableRef`
- result = default(CountTable[A])
- initImpl(result, initialSize)
- proc toCountTable*[A](keys: openArray[A]): CountTable[A] =
- ## Creates a new count table with every member of a container `keys`
- ## having a count of how many times it occurs in that container.
- result = initCountTable[A](keys.len)
- for key in items(keys): result.inc(key)
- proc `[]`*[A](t: CountTable[A], key: A): int =
- ## Retrieves the value at `t[key]` if `key` is in `t`.
- ## Otherwise `0` is returned.
- ##
- ## See also:
- ## * `getOrDefault<#getOrDefault,CountTable[A],A,int>`_ to return
- ## a custom value if the key doesn't exist
- ## * `[]= proc<#[]%3D,CountTable[A],A,int>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,CountTable[A],A>`_ for checking if a key
- ## is in the table
- assert(not t.isSorted, "CountTable must not be used after sorting")
- ctget(t, key, 0)
- template cntMakeEmpty(i) = t.data[i].val = 0
- template cntCellEmpty(i) = t.data[i].val == 0
- template cntCellHash(i) = hash(t.data[i].key)
- proc `[]=`*[A](t: var CountTable[A], key: A, val: int) =
- ## Inserts a `(key, value)` pair into `t`.
- ##
- ## See also:
- ## * `[] proc<#[],CountTable[A],A>`_ for retrieving a value of a key
- ## * `inc proc<#inc,CountTable[A],A,int>`_ for incrementing a
- ## value of a key
- assert(not t.isSorted, "CountTable must not be used after sorting")
- assert val >= 0
- if val == 0:
- delImplNoHCode(cntMakeEmpty, cntCellEmpty, cntCellHash)
- else:
- let h = rawGet(t, key)
- if h >= 0:
- t.data[h].val = val
- else:
- insertImpl()
- proc inc*[A](t: var CountTable[A], key: A, val = 1) =
- ## Increments `t[key]` by `val` (default: 1).
- runnableExamples:
- var a = toCountTable("aab")
- a.inc('a')
- a.inc('b', 10)
- doAssert a == toCountTable("aaabbbbbbbbbbb")
- assert(not t.isSorted, "CountTable must not be used after sorting")
- var index = rawGet(t, key)
- if index >= 0:
- inc(t.data[index].val, val)
- if t.data[index].val == 0:
- delImplIdx(t, index, cntMakeEmpty, cntCellEmpty, cntCellHash)
- else:
- if val != 0:
- insertImpl()
- proc len*[A](t: CountTable[A]): int =
- ## Returns the number of keys in `t`.
- result = t.counter
- proc smallest*[A](t: CountTable[A]): tuple[key: A, val: int] =
- ## Returns the `(key, value)` pair with the smallest `val`. Efficiency: O(n)
- ##
- ## See also:
- ## * `largest proc<#largest,CountTable[A]>`_
- assert t.len > 0, "counttable is empty"
- var minIdx = -1
- for h in 0 .. high(t.data):
- if t.data[h].val > 0 and (minIdx == -1 or t.data[minIdx].val > t.data[h].val):
- minIdx = h
- result.key = t.data[minIdx].key
- result.val = t.data[minIdx].val
- proc largest*[A](t: CountTable[A]): tuple[key: A, val: int] =
- ## Returns the `(key, value)` pair with the largest `val`. Efficiency: O(n)
- ##
- ## See also:
- ## * `smallest proc<#smallest,CountTable[A]>`_
- assert t.len > 0, "counttable is empty"
- var maxIdx = 0
- for h in 1 .. high(t.data):
- if t.data[maxIdx].val < t.data[h].val: maxIdx = h
- result.key = t.data[maxIdx].key
- result.val = t.data[maxIdx].val
- proc hasKey*[A](t: CountTable[A], key: A): bool =
- ## Returns true if `key` is in the table `t`.
- ##
- ## See also:
- ## * `contains proc<#contains,CountTable[A],A>`_ for use with the `in`
- ## operator
- ## * `[] proc<#[],CountTable[A],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,CountTable[A],A,int>`_ to return
- ## a custom value if the key doesn't exist
- assert(not t.isSorted, "CountTable must not be used after sorting")
- result = rawGet(t, key) >= 0
- proc contains*[A](t: CountTable[A], key: A): bool =
- ## Alias of `hasKey proc<#hasKey,CountTable[A],A>`_ for use with
- ## the `in` operator.
- return hasKey[A](t, key)
- proc getOrDefault*[A](t: CountTable[A], key: A; default: int = 0): int =
- ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
- ## integer value of `default` is returned.
- ##
- ## See also:
- ## * `[] proc<#[],CountTable[A],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,CountTable[A],A>`_ for checking if a key
- ## is in the table
- ctget(t, key, default)
- proc del*[A](t: var CountTable[A], key: A) {.since: (1, 1).} =
- ## Deletes `key` from table `t`. Does nothing if the key does not exist.
- ##
- ## See also:
- ## * `pop proc<#pop,CountTable[A],A,int>`_
- ## * `clear proc<#clear,CountTable[A]>`_ to empty the whole table
- runnableExamples:
- var a = toCountTable("aabbbccccc")
- a.del('b')
- assert a == toCountTable("aaccccc")
- a.del('b')
- assert a == toCountTable("aaccccc")
- a.del('c')
- assert a == toCountTable("aa")
- delImplNoHCode(cntMakeEmpty, cntCellEmpty, cntCellHash)
- proc pop*[A](t: var CountTable[A], key: A, val: var int): bool {.since: (1, 1).} =
- ## Deletes the `key` from the table.
- ## Returns `true`, if the `key` existed, and sets `val` to the
- ## mapping of the key. Otherwise, returns `false`, and the `val` is
- ## unchanged.
- ##
- ## See also:
- ## * `del proc<#del,CountTable[A],A>`_
- ## * `clear proc<#clear,CountTable[A]>`_ to empty the whole table
- runnableExamples:
- var a = toCountTable("aabbbccccc")
- var i = 0
- assert a.pop('b', i)
- assert i == 3
- i = 99
- assert not a.pop('b', i)
- assert i == 99
- var index = rawGet(t, key)
- result = index >= 0
- if result:
- val = move(t.data[index].val)
- delImplIdx(t, index, cntMakeEmpty, cntCellEmpty, cntCellHash)
- proc clear*[A](t: var CountTable[A]) =
- ## Resets the table so that it is empty.
- ##
- ## See also:
- ## * `del proc<#del,CountTable[A],A>`_
- ## * `pop proc<#pop,CountTable[A],A,int>`_
- clearImpl()
- t.isSorted = false
- func ctCmp[T](a, b: tuple[key: T, val: int]): int =
- result = system.cmp(a.val, b.val)
- proc sort*[A](t: var CountTable[A], order = SortOrder.Descending) =
- ## Sorts the count table so that, by default, the entry with the
- ## highest counter comes first.
- ##
- ## .. warning:: This is destructive! Once sorted, you must not modify `t` afterwards!
- ##
- ## You can use the iterators `pairs<#pairs.i,CountTable[A]>`_,
- ## `keys<#keys.i,CountTable[A]>`_, and `values<#values.i,CountTable[A]>`_
- ## to iterate over `t` in the sorted order.
- runnableExamples:
- import std/[algorithm, sequtils]
- var a = toCountTable("abracadabra")
- doAssert a == "aaaaabbrrcd".toCountTable
- a.sort()
- doAssert toSeq(a.values) == @[5, 2, 2, 1, 1]
- a.sort(SortOrder.Ascending)
- doAssert toSeq(a.values) == @[1, 1, 2, 2, 5]
- t.data.sort(cmp = ctCmp, order = order)
- t.isSorted = true
- proc merge*[A](s: var CountTable[A], t: CountTable[A]) =
- ## Merges the second table into the first one (must be declared as `var`).
- runnableExamples:
- var a = toCountTable("aaabbc")
- let b = toCountTable("bcc")
- a.merge(b)
- doAssert a == toCountTable("aaabbbccc")
- assert(not s.isSorted, "CountTable must not be used after sorting")
- for key, value in t:
- s.inc(key, value)
- when (NimMajor, NimMinor) <= (1, 0):
- proc merge*[A](s, t: CountTable[A]): CountTable[A] =
- ## Merges the two tables into a new one.
- runnableExamples:
- let
- a = toCountTable("aaabbc")
- b = toCountTable("bcc")
- doAssert merge(a, b) == toCountTable("aaabbbccc")
- result = initCountTable[A](nextPowerOfTwo(max(s.len, t.len)))
- for table in @[s, t]:
- for key, value in table:
- result.inc(key, value)
- proc `$`*[A](t: CountTable[A]): string =
- ## The `$` operator for count tables. Used internally when calling `echo`
- ## on a table.
- dollarImpl()
- proc `==`*[A](s, t: CountTable[A]): bool =
- ## The `==` operator for count tables. Returns `true` if both tables
- ## contain the same keys with the same count. Insert order does not matter.
- equalsImpl(s, t)
- iterator pairs*[A](t: CountTable[A]): (A, int) =
- ## Iterates over any `(key, value)` pair in the table `t`.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,CountTable[A]>`_
- ## * `keys iterator<#keys.i,CountTable[A]>`_
- ## * `values iterator<#values.i,CountTable[A]>`_
- ##
- ## **Examples:**
- ##
- ## ```Nim
- ## let a = toCountTable("abracadabra")
- ##
- ## for k, v in pairs(a):
- ## echo "key: ", k
- ## echo "value: ", v
- ##
- ## # key: a
- ## # value: 5
- ## # key: b
- ## # value: 2
- ## # key: c
- ## # value: 1
- ## # key: d
- ## # value: 1
- ## # key: r
- ## # value: 2
- ## ```
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mpairs*[A](t: var CountTable[A]): (A, var int) =
- ## Iterates over any `(key, value)` pair in the table `t` (must be
- ## declared as `var`). The values can be modified.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,CountTable[A]>`_
- ## * `mvalues iterator<#mvalues.i,CountTable[A]>`_
- runnableExamples:
- var a = toCountTable("abracadabra")
- for k, v in mpairs(a):
- v = 2
- doAssert a == toCountTable("aabbccddrr")
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator keys*[A](t: CountTable[A]): lent A =
- ## Iterates over any key in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,CountTable[A]>`_
- ## * `values iterator<#values.i,CountTable[A]>`_
- runnableExamples:
- var a = toCountTable("abracadabra")
- for k in keys(a):
- a[k] = 2
- doAssert a == toCountTable("aabbccddrr")
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield t.data[h].key
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator values*[A](t: CountTable[A]): int =
- ## Iterates over any value in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,CountTable[A]>`_
- ## * `keys iterator<#keys.i,CountTable[A]>`_
- ## * `mvalues iterator<#mvalues.i,CountTable[A]>`_
- runnableExamples:
- let a = toCountTable("abracadabra")
- for v in values(a):
- assert v < 10
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mvalues*[A](t: var CountTable[A]): var int =
- ## Iterates over any value in the table `t` (must be
- ## declared as `var`). The values can be modified.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,CountTable[A]>`_
- ## * `values iterator<#values.i,CountTable[A]>`_
- runnableExamples:
- var a = toCountTable("abracadabra")
- for v in mvalues(a):
- v = 2
- doAssert a == toCountTable("aabbccddrr")
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- # ---------------------------------------------------------------------------
- # ---------------------------- CountTableRef --------------------------------
- # ---------------------------------------------------------------------------
- proc inc*[A](t: CountTableRef[A], key: A, val = 1)
- proc newCountTable*[A](initialSize = defaultInitialSize): CountTableRef[A] =
- ## Creates a new ref count table that is empty.
- ##
- ## See also:
- ## * `newCountTable proc<#newCountTable,openArray[A]>`_ for creating
- ## a `CountTableRef` from a collection
- ## * `initCountTable proc<#initCountTable>`_ for creating a
- ## `CountTable`
- new(result)
- {.noSideEffect.}:
- result[] = initCountTable[A](initialSize)
- proc newCountTable*[A](keys: openArray[A]): CountTableRef[A] =
- ## Creates a new ref count table with every member of a container `keys`
- ## having a count of how many times it occurs in that container.
- result = newCountTable[A](keys.len)
- {.noSideEffect.}:
- for key in items(keys): result.inc(key)
- proc `[]`*[A](t: CountTableRef[A], key: A): int =
- ## Retrieves the value at `t[key]` if `key` is in `t`.
- ## Otherwise `0` is returned.
- ##
- ## See also:
- ## * `getOrDefault<#getOrDefault,CountTableRef[A],A,int>`_ to return
- ## a custom value if the key doesn't exist
- ## * `inc proc<#inc,CountTableRef[A],A,int>`_ to inc even if missing
- ## * `[]= proc<#[]%3D,CountTableRef[A],A,int>`_ for inserting a new
- ## (key, value) pair in the table
- ## * `hasKey proc<#hasKey,CountTableRef[A],A>`_ for checking if a key
- ## is in the table
- result = t[][key]
- proc `[]=`*[A](t: CountTableRef[A], key: A, val: int) =
- ## Inserts a `(key, value)` pair into `t`.
- ##
- ## See also:
- ## * `[] proc<#[],CountTableRef[A],A>`_ for retrieving a value of a key
- ## * `inc proc<#inc,CountTableRef[A],A,int>`_ for incrementing a
- ## value of a key
- assert val > 0
- {.noSideEffect.}:
- t[][key] = val
- proc inc*[A](t: CountTableRef[A], key: A, val = 1) =
- ## Increments `t[key]` by `val` (default: 1).
- runnableExamples:
- var a = newCountTable("aab")
- a.inc('a')
- a.inc('b', 10)
- doAssert a == newCountTable("aaabbbbbbbbbbb")
- {.noSideEffect.}:
- t[].inc(key, val)
- proc smallest*[A](t: CountTableRef[A]): tuple[key: A, val: int] =
- ## Returns the `(key, value)` pair with the smallest `val`. Efficiency: O(n)
- ##
- ## See also:
- ## * `largest proc<#largest,CountTableRef[A]>`_
- t[].smallest
- proc largest*[A](t: CountTableRef[A]): tuple[key: A, val: int] =
- ## Returns the `(key, value)` pair with the largest `val`. Efficiency: O(n)
- ##
- ## See also:
- ## * `smallest proc<#smallest,CountTable[A]>`_
- t[].largest
- proc hasKey*[A](t: CountTableRef[A], key: A): bool =
- ## Returns true if `key` is in the table `t`.
- ##
- ## See also:
- ## * `contains proc<#contains,CountTableRef[A],A>`_ for use with the `in`
- ## operator
- ## * `[] proc<#[],CountTableRef[A],A>`_ for retrieving a value of a key
- ## * `getOrDefault proc<#getOrDefault,CountTableRef[A],A,int>`_ to return
- ## a custom value if the key doesn't exist
- result = t[].hasKey(key)
- proc contains*[A](t: CountTableRef[A], key: A): bool =
- ## Alias of `hasKey proc<#hasKey,CountTableRef[A],A>`_ for use with
- ## the `in` operator.
- return hasKey[A](t, key)
- proc getOrDefault*[A](t: CountTableRef[A], key: A, default: int): int =
- ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
- ## integer value of `default` is returned.
- ##
- ## See also:
- ## * `[] proc<#[],CountTableRef[A],A>`_ for retrieving a value of a key
- ## * `hasKey proc<#hasKey,CountTableRef[A],A>`_ for checking if a key
- ## is in the table
- result = t[].getOrDefault(key, default)
- proc len*[A](t: CountTableRef[A]): int =
- ## Returns the number of keys in `t`.
- result = t.counter
- proc del*[A](t: CountTableRef[A], key: A) {.since: (1, 1).} =
- ## Deletes `key` from table `t`. Does nothing if the key does not exist.
- ##
- ## See also:
- ## * `pop proc<#pop,CountTableRef[A],A,int>`_
- ## * `clear proc<#clear,CountTableRef[A]>`_ to empty the whole table
- del(t[], key)
- proc pop*[A](t: CountTableRef[A], key: A, val: var int): bool {.since: (1, 1).} =
- ## Deletes the `key` from the table.
- ## Returns `true`, if the `key` existed, and sets `val` to the
- ## mapping of the key. Otherwise, returns `false`, and the `val` is
- ## unchanged.
- ##
- ## See also:
- ## * `del proc<#del,CountTableRef[A],A>`_
- ## * `clear proc<#clear,CountTableRef[A]>`_ to empty the whole table
- pop(t[], key, val)
- proc clear*[A](t: CountTableRef[A]) =
- ## Resets the table so that it is empty.
- ##
- ## See also:
- ## * `del proc<#del,CountTableRef[A],A>`_
- ## * `pop proc<#pop,CountTableRef[A],A,int>`_
- clear(t[])
- proc sort*[A](t: CountTableRef[A], order = SortOrder.Descending) =
- ## Sorts the count table so that, by default, the entry with the
- ## highest counter comes first.
- ##
- ## **This is destructive! You must not modify `t` afterwards!**
- ##
- ## You can use the iterators `pairs<#pairs.i,CountTableRef[A]>`_,
- ## `keys<#keys.i,CountTableRef[A]>`_, and `values<#values.i,CountTableRef[A]>`_
- ## to iterate over `t` in the sorted order.
- t[].sort(order = order)
- proc merge*[A](s, t: CountTableRef[A]) =
- ## Merges the second table into the first one.
- runnableExamples:
- let
- a = newCountTable("aaabbc")
- b = newCountTable("bcc")
- a.merge(b)
- doAssert a == newCountTable("aaabbbccc")
- s[].merge(t[])
- proc `$`*[A](t: CountTableRef[A]): string =
- ## The `$` operator for count tables. Used internally when calling `echo`
- ## on a table.
- dollarImpl()
- proc `==`*[A](s, t: CountTableRef[A]): bool =
- ## The `==` operator for count tables. Returns `true` if either both tables
- ## are `nil`, or neither is `nil` and both contain the same keys with the same
- ## count. Insert order does not matter.
- if isNil(s): result = isNil(t)
- elif isNil(t): result = false
- else: result = s[] == t[]
- iterator pairs*[A](t: CountTableRef[A]): (A, int) =
- ## Iterates over any `(key, value)` pair in the table `t`.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,CountTableRef[A]>`_
- ## * `keys iterator<#keys.i,CountTableRef[A]>`_
- ## * `values iterator<#values.i,CountTableRef[A]>`_
- ##
- ## **Examples:**
- ##
- ## ```Nim
- ## let a = newCountTable("abracadabra")
- ##
- ## for k, v in pairs(a):
- ## echo "key: ", k
- ## echo "value: ", v
- ##
- ## # key: a
- ## # value: 5
- ## # key: b
- ## # value: 2
- ## # key: c
- ## # value: 1
- ## # key: d
- ## # value: 1
- ## # key: r
- ## # value: 2
- ## ```
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mpairs*[A](t: CountTableRef[A]): (A, var int) =
- ## Iterates over any `(key, value)` pair in the table `t`. The values can
- ## be modified.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,CountTableRef[A]>`_
- ## * `mvalues iterator<#mvalues.i,CountTableRef[A]>`_
- runnableExamples:
- let a = newCountTable("abracadabra")
- for k, v in mpairs(a):
- v = 2
- doAssert a == newCountTable("aabbccddrr")
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield (t.data[h].key, t.data[h].val)
- assert(len(t) == L, "table modified while iterating over it")
- iterator keys*[A](t: CountTableRef[A]): A =
- ## Iterates over any key in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,CountTable[A]>`_
- ## * `values iterator<#values.i,CountTable[A]>`_
- runnableExamples:
- let a = newCountTable("abracadabra")
- for k in keys(a):
- a[k] = 2
- doAssert a == newCountTable("aabbccddrr")
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield t.data[h].key
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator values*[A](t: CountTableRef[A]): int =
- ## Iterates over any value in the table `t`.
- ##
- ## See also:
- ## * `pairs iterator<#pairs.i,CountTableRef[A]>`_
- ## * `keys iterator<#keys.i,CountTableRef[A]>`_
- ## * `mvalues iterator<#mvalues.i,CountTableRef[A]>`_
- runnableExamples:
- let a = newCountTable("abracadabra")
- for v in values(a):
- assert v < 10
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- iterator mvalues*[A](t: CountTableRef[A]): var int =
- ## Iterates over any value in the table `t`. The values can be modified.
- ##
- ## See also:
- ## * `mpairs iterator<#mpairs.i,CountTableRef[A]>`_
- ## * `values iterator<#values.i,CountTableRef[A]>`_
- runnableExamples:
- var a = newCountTable("abracadabra")
- for v in mvalues(a):
- v = 2
- doAssert a == newCountTable("aabbccddrr")
- let L = len(t)
- for h in 0 .. high(t.data):
- if t.data[h].val != 0:
- yield t.data[h].val
- assert(len(t) == L, "the length of the table changed while iterating over it")
- proc hash*[K,V](s: Table[K,V]): Hash =
- for p in pairs(s):
- result = result xor hash(p)
- result = !$result
- proc hash*[K,V](s: OrderedTable[K,V]): Hash =
- for p in pairs(s):
- result = result !& hash(p)
- result = !$result
- proc hash*[V](s: CountTable[V]): Hash =
- for p in pairs(s):
- result = result xor hash(p)
- result = !$result
|