KX Community

Find answers, ask questions, and connect with our KX Community around the world.
KX Community Guidelines

Home Forums kdb+ how to find the first element for each row which satisfy the condition

  • how to find the first element for each row which satisfy the condition

    Posted by chan_chenyanj on May 14, 2022 at 12:00 am

    suppose i have a table

    t: ([]isMatched: (1b,1b,0b,0b;1b,1b,0b,0b;0b,0b,1b,1b); index:((0,1,2,3);(0,1,2,3);(0,1,2,3));id: ((`a,`b,`c,`d);(`a,`b,`c,`d);(`a,`b,`c,`d)))

     

    so each row will find use the first element in idx which the corresponding element in isMatched =true. Once the index is find, then that corresponding id is no longer available to pick for rows after. For example, first row idx = 0 is working as first element of isMatched for row 0 is true, Thus id a is no longer available. then for second row it the first element in idx column is 1 as isMatched is ture for 0 and 1 but 0 element of id is selected already. idx is of same length (but might be different order) but id is same for all rows. len of isMatched, idx, id is same too. Is there any better algorithm to solve it in q?

     

    isMatched   idx            id

    ————————-
    1100b             0 1 2 3        a b c d
    1100b            0 1 2 3         a b c d
    0011b            0 1 2 3          a b c d

    chan_chenyanj replied 9 months, 1 week ago 2 Members · 2 Replies
  • 2 Replies
  • chan_chenyanj

    Member
    May 14, 2022 at 12:00 am

    or t can be like this

    t: ([]isMatched: (1b,1b,0b,0b;1b,1b,0b,0b;0b,0b,1b,1b); index:((0,1,2,3);(1,0,2,3);(0,1,2,3));id: ((`a,`b,`c,`d);(`a,`b,`c,`d);(`a,`b,`c,`d)))
  • Laura

    Administrator
    May 16, 2022 at 12:00 am

     

    q)u 
    isMatched index id 
    ------------------------- 
    1100b 0 1 2 3 a b c d 
    1100b 1 0 2 3 a b c d 
    0011b 0 1 2 3 a b c d 
    
    q)fw:first where@ / composition 
    q)select index:index@'j,id:id@'j from update j:fw each isMatched from u 
    index id 
    -------- 
    0 a 
    1 a 
    2 c

     

    Or you might prefer the same thing as vector operations:

     

    q)u[`index`id]@':fw each u`isMatched 
    0 1 2 
    a a c 
    
    q)ts:10000 select index:index@'j,id:id@'j from update j:fw each isMatched from u 
    65 2832 
    
    q)ts:10000 u[`index`id]@':fw each u`isMatched 
    21 1376

     

    In the vector expression, fw each u`isMatched corresponds to fw each isMatched from u. But instead of forming column j of a new temporary table, it is applied direct to the index and id columns of u. Notice how Each Left : takes Index At Each @' as its argument to derive binary function Index At Each Each Left.

    Your sublists are short; if they were longer you might prefer faster ?'[;1b] to fw each:

     

    q)ts:10000 select index:index@’j,id:id@’j from update j:?'[;1b] isMatched from u

    61 3056

    q)ts:10000 u[`index`id]@’:u[`isMatched]?’

    1b

    16 1568

     

Log in to reply.