dict_get

Abstract

Get a value from a hashtable

Description

A hashtable is a mapping from a key to a value. The dict_ family of opcodes implement a hashtable mapping either strings or integers to strings or floats. dict_get returns the value for a given key. If the key is not present, a default value is returned (the empty string for string values, or an user given default for number values)

Syntax

kvalue dict_get idict, Skey, idefault=0
ivalue dict_get idict, Skey, idefault=0
kvalue dict_get idict, kkey, idefault=0
ivalue dict_get idict, ikey, idefault=0
Svalue dict_get idict, Skey
Svalue dict_geti idict, Skey  ; (init time version)
Svalue dict_get idict, kkey

Note

The type of key and value depend on the type definition of the dict, see dict_new In the case of a dict of type "str:str", dict_get returns an empty string if the key is not found

Arguments

  • ìdict: the handle of the dict, as returned by dict_new
  • Skey / kkey: the key to be queries, as previously set by dict_set
  • idefault: if the key is not present, this value is returned (defaults to 0)

Output

  • kvalue / Svalue: the value corresponding to the key, or a default if the key is not found

  • For dicts with a string value, an empty string is returned when the key is not found.

  • For dicts with a numeric value, a user given default is returned (default=0)

Execution Time

  • Init
  • Performance

dict_get executes at i-time and k-time depending on the output value. In the case of a dict of type "str:str" dict_get runs at k-time. Use dict_geti for an init time version

Examples

<CsoundSynthesizer>
<CsOptions>
; -odac  -iadc    ;;;RT audio out and in

</CsOptions>
<CsInstruments>

sr = 44100
ksmps = 32
nchnls = 2

instr 1 
  ; create a local dict, mapping strings to numbers
  idict dict_new "sf"

  ; set key a key:value pair
  dict_set idict, "bar", 123

  ; retrieve the value
  kbar dict_get idict, "bar"

  ; get a non-existent key, will output the default
  kfoo dict_get idict, "foo", -1 

  printf ">>>> bar: %f,  foo: %f \n", 1, kbar, kfoo 

  ; now create another dict, this one will outlive this note
  idict2 dict_new "ss", 1, "baz", "bazvalue", "foo", "foovalue"

  ; schedule another inst, pass this dict
  event "i", 2, 0, 1, idict2

  turnoff

endin

instr 2
  idict = p4
  Sbaz = dict_get(idict, "baz")
  printf "instr 2, kbaz = %s \n", 1, Sbaz

  ; free dict at the end of this note
  dict_free idict, 1  
  turnoff
endin

; schedule 1, 0, 1

</CsInstruments>
<CsScore>

i 1 0 2

</CsScore>
</CsoundSynthesizer> 
<CsoundSynthesizer>
<CsOptions>

</CsOptions>
<CsInstruments>

/*

  # Example file for dict_get

  ## dict_get

    kvalue dict_get idict, "key" [, kdefault=0]


  Get the value at a given key. For string values, an empty string
  is returned when the key is not found. For int values, a default 
  value given by the user is returned when the key is not found.

*/

ksmps = 64
nchnls = 2
0dbfs = 1

instr 1
  ; create a local dict, mapping strings to numbers
  idict dict_new "sf"
  dict_free idict

  ; set key a key:value pair
  dict_set idict, "bar", 123

  ; retrieve teh value
  kbar dict_get idict, "bar"

  ; get a non-existent key, will output the default
  kfoo dict_get idict, "foo", -1 

  printf ">>>> bar: %f,  foo: %f \n", 1, kbar, kfoo 

  ; now create another dict, mapping strings to strings
  idict2 dict_new "ss"

  dict_set idict2, "baz", "bazvalue"
  dict_set idict2, "hoo", "hoovalue"

  Sbaz dict_get idict2, "baz"
  Shoo dict_get idict2, "hoo"

  printf ">>>> baz: %s,  hoo: %s \n", 1, Sbaz, Shoo 

  turnoff
endin


instr 2
  ;; set and get 
  if timeinstk() > 1 kgoto perf    ;; this starts at 1

  imaxcnt = 100
  idict dict_new "ss"

  kcnt = 0
  while kcnt < imaxcnt do
    Skey sprintfk "key_%d", kcnt
    Svalue sprintfk "value_%d", kcnt 
    dict_set idict, Skey, Svalue 
    kcnt += 1 
  od 

perf:
  kcnt = 0
  while kcnt < imaxcnt do 
    Skey  sprintfk "key_%d", kcnt
    ; the same for get, the key can change at k-time
    Svalue dict_get idict, Skey
    printf "key: %s,  value: %s \n", kcnt, Skey, Svalue 
    kcnt += 1
  od 
endin

instr 3
  /*

  dict_iter

  xkey, xvalue, kidx dict_iter ihandle [,kreset=1]

  kidx: holds the number of pairs yielded since last reset. It 
        is set to -1 when iteration has stopped 
        (in this case, xkey and xvalue are invalid and should not
        be used)
  kreset = 0  -> after iterating over all pairs iteration stops
                 In this mode, iteration happens at most once
           1  -> iteration starts over every k-cycle
           2  -> iteration restarts after stopping   
  */

  kt timeinstk 
  if kt > 1 kgoto perf 

  idict dict_new "sf"
  dict_set idict, "foo", 1
  dict_set idict, "bar", 2
  dict_set idict, "baz", 15
  dict_set idict, "bee", 9

perf:
  ; iterate with a while loop
  kidx = 0
  while kidx < dict_size(idict) - 1 do 
    Skey, kvalue, kidx dict_iter idict 
    printf "while) %s -> %f \n", kidx+kt*1000, Skey, kvalue
  od   

  ; the same but with goto
loop:
  Skey, kvalue, kidx dict_iter idict
  if kidx == -1 goto break
  printf "loop) %s -> %f \n", kidx+kt*1000, Skey, kvalue
  kgoto loop
break:
endin

instr 4
  ; test deleting a key
  ; ~~~~~~~~~~~~~~~~~~~

  idict dict_new "ss"

  ; set a key:value pair
  dict_set idict, "foo", "foovalue"

  ; get the value, print it
  Sfoo dict_get idict, "foo"
  printf "key: foo  value: %s \n", 1, Sfoo

  ; dict_set without value deletes the key:value pair
  dict_set idict, "foo"

  ; now check that the pair is gone
  Sfoo dict_get idict, "foo"
  if(strlen(Sfoo)==0) then 
    printf "key does not exist \n", 1
  endif

  turnoff
endin


instr 5
  ; dicts can be passed between instruments
  ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  if timeinstk() > 1 goto perf

  ; create a dict which survives this note
  idict1 dict_new "sf", 1

  ; set some initial values once 
  dict_set idict1, "foo", 1
  dict_set idict1, "bar", 2

  ; launch instr 6, which will outlive this note, pass idict as p4
  event "i", "midifydict", 0, p3+1, idict1 

perf:
  kfoo dict_get idict1, "foo"
  printk2 kfoo

endin

instr modifydict
  ; here we modify instr 5's dictionary
  ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  ; the dict was created by instr 5
  idict = p4

  kfoo line 0, p3-1, 10
  dict_set idict, "foo", kfoo 

  dict_free idict, 1 ; 1 = free dict when note ends
endin

instr 7
  ; it is possible to create a new dict and set initial
  ; values at once. This is only executed at i-time
  idict dict_new "sf", 0, "foo", 10, "bar", 20, "baz", 30
  kbaz dict_get idict, "baz"
  kbar dict_get idict, "bar"
  kxx dict_get idict, "xx", 99
  printf "baz: %f  bar: %f  xx: %f \n", 1, kbaz, kbar, kxx 
  turnoff
endin

instr 8
  ; get all the keys as an array
  idict1 dict_new "sf", 0, "keyA", 1, "keyB", 2, "keyC", 3
  SKeys[] dict_query idict1, "keys"
  printarray SKeys

  idict2 dict_new "if", 0, 1,100, 10,1000, 2,200
  kKeys[] dict_query idict2, "keys"
  printarray kKeys, 1, "%.0f"

  ; get values as an array
  idict3 dict_new "is", 0, 10, "foo", 20, "bar", 30, "baz"
  Svals[] dict_query idict3, "values"
  printarray Svals

  kVals[] dict_query idict2, "values"
  printarray kVals

  turnoff
endin

; One convenient use of dicts is to pass arguments to an instr
instr 100
  ; create our communication dict, set initial values
  idict dict_new "sf", "amp", 0.1, "freq", 1000
  ; the launched instr will last longer, so will have to deal with
  ; this dict ceasing to exist
  event_i "i", 101, 0, p3+1, idict

  ; now we can control the synth with the dict
  dict_set idict, "freq", linseg:k(440, p3, 455)

  a0 oscili 0.1, 440
  outch 1, a0 
endin

; a variation on dict_get where we either get the value corresponding to a key,
; or the last value, if the dict does not exist
opcode dict_receive, k,iSi 
  idict, Skey, ival0 xin
  klast init ival0
  if (dict_size(idict) > 0 ) then
    kval dict_get idict, Skey, ival0
    klast = kval
  else 
    kval = klast 
  endif 
  xout kval 
endop

instr 101
  idict = p4
  ; get the value for a given key. when the dict does not exist, just
  ; outputs the last value
  kamp dict_receive idict, "amp", 0.1 
  kfreq dict_receive idict, "freq", 1000
  a0 oscili kamp, kfreq 
  outch 2, a0
endin

instr 200
  idict dict_new "str:any", "foo", "fooval", "bar", 10
  dict_print idict
  Sfoo dict_get idict, "foo"
  kbar dict_get idict, "bar"
  printf "foo=%s, bar=%f \n", 1, Sfoo, kbar
  dict_set idict, "baz", 0.5
  ibaz dict_get idict, "baz"
  Smoo = "moo!"
  dict_set idict, "moo", Smoo
  printf "baz=%f,  moo=%s \n", 1, ibaz, Smoo
  turnoff
endin  

</CsInstruments>
<CsScore>
; i 1 0 0.01
; i 2 0 0.01
; i 8 0 0.1
; i 100 0 10
i 200 0 1
f 0 1
</CsScore>
</CsoundSynthesizer>

See also

Credits

Eduardo Moguillansky, 2019