upserting values of different types to a dictionary

Viewed 347

This one works:

d1:`t1`t2`idx!(2017.01.01;2018.01.01;42)

But this one fails (type error):

d2:()!()
d2[`t1]:2017.01.01
d2[`t2]:2018.01.01
d2[`idx]:42

Is there a workaround? For better readability, I'd like to populate the dictionary key by key (line by line). In reality, it is longer.

3 Answers

When you define the dictionary as d:()!(), the first thing you insert (in this case a date) will make the type of the dictionary only take values of type -14h.

Standard practice is to initialise the dict with an untyped value to stop the value becoming a simple vector

q)d2:enlist[`]!enlist(::)
q)d2[`t1]:2017.01.01
q)d2[`t2]:2018.01.01
q)d2[`idx]:42
q)d2
   | ::
t1 | 2017.01.01
t2 | 2018.01.01
idx| 42

First approach defines a general dictionary whose values are a general list, which means it can store values of any type. This is also used in defining tables as tables can store columns with different types.

In Second approach, when you insert the first value inside the dictionary, it sets the type of value list of the dictionary to that element type. So it is a simple list now.

  q) d2: ()!()
  q) d2[`t1]:2017.01.01
  q) type value d2  / 14h

That means now dictionary values cant be a general list and can only store date type items in it.

To create a general dictionary (which stores general list as values) insert first entry value as null (::). This is what is used by namespace dictionaries.

  q)  d2: ()!()
  q)  d2[`]:(::) 

Now it can store any value.

  q) d2[`t2]:2018.01.01
  q) d2[`idx]:42

Alternatively, you can concatenate the 2 dictionaries instead of adding the entry. This comes in handy when you need to add something to an existing dictionary. Not exactly the OPs scenario but it fits the headline and so others landing here may find it useful.

d2:()!()
d2[`t1]:2017.01.01
d2[`t2]:2018.01.01
d2:d2,(enlist `idx)!(enlist 42)
d2

t1 | 2017.01.01
t2 | 2018.01.01
idx| 42
Related