Good evening everyone!
Unfortunately I’m not having the time I would like to study KDB + and Q.
I am at the very beginning of my studies.
Following all indications from the official website (learn section).
I’m still thinking of simple examples to solve (not from the real world).
Can someone check this simple exercise for me?
Given any list, display only items that are not repeated.
l: 1 2 4 5 7 9 2 2 5
Expected response: 1 4 7 9
My first solution:
q) where 1= count each group l
q) 1 4 7 9
I will continue to think about other solutions.
Could someone give me a more “optimized” solution?
Thank you for your help!
I imagine that your solution is the one that most people would use in practice.
For the sake of variety:
q){x where d&1_(d:differ x),1b}asc 1 2 4 5 7 9 2 2 5
1 4 7 9
Sort the list then if an entry is different from the previous entry and different to the next it’s unique.
Terry
Or possibly more efficiently - if an entry matches the previous or matches the next in the sorted list then exclude it
q){x where not d|next d:(~':)x}asc 1 2 4 5 7 9 2 2 5
1 4 7 9
Terry
TerryLynch, thank you!
I’m still starting and for that reason I don’t know many commands / functions.
I will take advantage of your examples to learn new ways to code.
Em sexta-feira, 13 de novembro de 2020 às 06:15:29 UTC-3, TerryLynch escreveu:
I imagine that your solution is the one that most people would use in practice.
For the sake of variety:
q){x where d&1_(d:differ x),1b}asc 1 2 4 5 7 9 2 2 5
1 4 7 9
Sort the list then if an entry is different from the previous entry and different to the next it’s unique.
Terry
No problem. Thinking a little further (last one I swear!), if it’s a uniform list whose elements can be compared using equals/not-equals then it simplifies to:
q){x where(x<>prev x)&x<>next x}asc 1 2 4 5 7 9 2 2 5
1 4 7 9
The other approach using differ and identical-each-prior would work for general/mixed lists too.
Terry
Couple more ways-
q)l where 1=sum l=/:l
1 4 7 9
q)r where {y*x>=y}':[s 0;1_s,last s:differ r:asc l]
1 4 7 9
-Ajay
another way
q){d:distinct x;d where(x bin d)=x binr d} asc l
1 4 7 9
Attila
November 17, 2020, 9:10am
8
that is a very interesting idea
to expand on TerryLynch’s solution by relaxing the constraint on types we can do
a:{x where differ &differ[first x; next x:asc x]}
this works with nested too
q)a (1 2;2 3; 1 2;4 5;0 0; 0 0)
2 3
4 5
Attila
November 17, 2020, 9:42am
9
ah, i missed that TerryLynch originally had something quite similar
interestingly the fastest solution is hand-roll the frequency collection (ie, count each group)
q)l:100000?10000
q)\ts:100 {d:distinct x;d where(x bin d)=x binr d} asc l
481 2229056
q)\ts:100 where 1=count each group l
239 4064864
q)\ts:100 {x where not d|next d:(~':)x}asc l
187 2229056
q)\ts:100 {d where 1=@[count[d]#0 ;(d:distinct x)?x;+;1]}l
78 2360128
q)\ts:100 {d where 1i=@[count[d]#0i ;(d:distinct x)?x;+;1i]}l
68 1770400
ajay1
November 17, 2020, 12:02pm
10
building on it you can get away with allocating new object and shorten it further.
q)\t:100 {d where (d+1)=@[d;(d:distinct x)?x;+;1]}l
67
q)\t:100 {d where 1=@[count[d]#0i ;(d:distinct x)?x;+;1i]}l
69
wp1
November 17, 2020, 12:47pm
11
another version worth noting (unfortunately slightly slower on my machine):
q)\ts:100 {d:distinct x; d where (x?d)=(-1+count x)-reverse ?d}l
131 1442672
q)\ts:100 {d where 1i=@[count[d]#0i ;(d:distinct x)?x;+;1i]}l
113 1770528
ajay1
November 17, 2020, 3:05pm
12
Caveta, this will only work for simple integer types
Can further improve one of the earlier solutions posted by Attila, using differ only once
q)l:100000?10000
q)\ts:100 {x where differ &differ[first x; next x:asc x]} l
125 3277584
q)\ts:100 {x where (1_d,last d)&d:differ[x:asc x]} l
108 2229008
-Ajay