Entries in # (4)

How do I split a list?

If you want to split the list into lists of equal size, see this related faq on the # (take) operator.

If you want to split a string on a delimiter, use the vs (vector from scalar) function:

q)" " vs "The quick brown fox"
"The"
"quick"
"brown"
"fox"
q)", " vs "Hello, world!"
"Hello"
"world!"
q)

When its left argument is the null symbol, `, the vs function breaks apart a symbol on dots:

q)` vs `foo.bar.baz
`foo`bar`baz
q)

Those are the most common cases. We can also split a list into lists of varying length by passing a list of indexes as the left argument to the _ (cut) operator:

q)0 1 4 9 _ til 10
,0
1 2 3
4 5 6 7 8
,9
q)

To split a list of some type other than char using a delimiter is a little more complicated. We start by finding the indexes in the list that match the delimiter:

q)list: 1 2 0 3 4 0 5 6
q)delimiter: 0
q)indexes: where delimiter = list
q)indexes
2 5
q)

Now we can break list into pieces using the _ (cut) operator as above:

q)indexes _ list
0 3 4
0 5 6
q)

This is almost what we want. We'll use _/: (drop-each-right) to get rid of the delimiters:

q)1 _/: indexes _ list
3 4
5 6
q)

We can grab the first element of the result with # (take):

q)first[indexes] # list
1 2
q)

Then we can just join (using ,) the two together:

q)(enlist first[indexes] # list), 1 _/: indexes _ list
1 2
3 4
5 6
q)

Note that we must call enlist on the front of the list or else we'll get something a little different from what we intended:

q)(first[indexes] # list), 1 _/: indexes _ list
1
2
3 4
5 6
q)

Lastly, we can generalize to non-atomic types by replacing = with ~/: (match-each-right):

split: {[list; delimiter]
    indexes: where delimiter ~/: list;
    front: first[indexes] # list;
    rest: 1 _/: indexes _ list;
    : (enlist front), rest;
    }

How can I slice a vector into a series of vectors of length n?

By passing the # (take) operator a pair as its first (i.e., left) argument:

q)2 5 # til 10
0 1 2 3 4
5 6 7 8 9

When # is used in this way, it is referred to as "reshape." We like to call this, "taking a box." Just like when you apply # with an integer left argument, taking a box stops when you have taken as many items as requested, leaving the rest behind:

q)3 3 # til 10
0 1 2
3 4 5
6 7 8

Similarly, when you over-take a box, you start over from the beginning of the source:

q)4 3 # til 10
0 1 2
3 4 5
6 7 8
9 0 1

If you want to take all the items from the source, pass 0N as the first element of the box:

q)0N 2 # til 10
0 1
2 3
4 5
6 7
8 9

If you take a whole box, but the elements from the source don't fit, you end up with a short list in the last row:

q)0N 3 # til 10
0 1 2
3 4 5
6 7 8
,9
q)

See also: cut and faq on _ (drop)

I noticed a list with a `s# prefix attached. What does this mean?

`s is one of q's data attributes, and indicates that the data in the list is sorted. When q knows that a list is sorted, it can perform some operations much faster. In contrast to the other attribute types, the sorted attribute has zero memory overhead (no data structure needs to be created to support it):

q)d: (-10000 ? `4) ¡ til 10000
q)key d
`namk`eefb`dnkg`pfme`ndpk`bhck`bdga`hkdk`gpja`oiof..
q)value d
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ..
q)\t do[100000; d key[d] 5000]
443
q)d: (asc key d) ! value[d] iasc key d
q)key d
`s#`aaab`aaak`aaap`aabb`aabn`aace`aadj`aaeg`aaeh`a..
q)\t do[100000; d key[d] 5000]
89
q)

Notice that value d above did not have the `s attribute; that is, the til function does not return a list with the `s attribute applied. In general, for a list to have the `s attribute, you must either sort the list (with asc as above) or let q know explicitly that the list is sorted by applying the `s attribute to a list that you know is already sorted:

q)x: `s # til 10
q)x
`s#0 1 2 3 4 5 6 7 8 9
q)

If you try to apply `s to a list that isn't actually sorted, you'll get an 's-fail error:

q)`s # 3 2 1
's-fail
q)

You can add elements to the end of a sorted list without losing the sorted attribute if the new elements do not violate the sorted-ness of the result:

q)x: `s # 1 2 3
q)x
`s#1 2 3
q)x ,: 4 5 6
q)x
`s#1 2 3 4 5 6
q)x ,: 7 7 7
q)x
`s#1 2 3 4 5 6 7 7 7

However, other modifications to a sorted list will cause the list to lose its attribute:

q)x: `s # 1 2 3
q)x
`s#1 2 3
q)x, 0
1 2 3 0
q)reverse x / reverse function removes it
3 2 1
q)

This is true even if the modifications result in a sorted list:

q) x: `s # 1 2 3
q)1 _ x
2 3
q)2 # x
1 2
q)

You can remove the sorted attribute explicitly by applying a null attribute to the list:

q)`#1 2 3 / application of a null attribute
1 2 3

See also the following function definitions: attr and #.

For even more detail, see Section 42 of the Abridged Q Language Manual.

How do I efficiently retrieve the first n rows of a query result?

select[n]. The first example below retrieves the first 10 rows, whereas the second example retrieves the last 10 rows:

select [10] from table where date=2011.02.27
select [-10] from table where date=2011.02.27

If the table is in memory, you can use the virtual column i to retrieve a specific range of rows:

select from table where i within (begin; end)

If you want to retrieve specific rows by index from a partitioned table, use .Q.ind.

C.f. # (take) and sublist