join_by
| Definition: | sequence res = join_by(sequence s, integer step, n, object step_pad="   ", n_pad="\n", string fmt="", integer skip=0) |
| Description: |
The join_by routine allows columnisation of results across the screen for easier reading.
Best illustrated by example, join_by iteratively interleaves up to n blocks of size step with step_pad, before joining with n_pad, repeated as necessary up to length(s) - however, typically you would experiment with different values until finding a layout that you like, so fully "grokking" what this really does is not particularly helpful, anyway. One particularly common pattern turns out to be a step of 1, a width in n, and a single space step_pad, at least that is for many rosettacode tasks. Fairly obviously if a non-empty fmt is provided it is applied, via sprintf(), to each element of s from skip+1 onwards (so by default to all, with skip being ignored when fmt is ""), as part of the joining process. Segments are expected to be padded to a consistent length before this routine is called, or fmt used to the same effect, in order to achieve proper alignment. Note that n_pad is duplicated when step>1 between each (n*step)-block, but only occurs once at the end, unless a trailing "" is supplied. When step=1, n_pad occurs once between each n-block, and only at the end in cases where a trailing "" has been provided. Uses join internally. The default for step_pad is three spaces. Returns a string or sequence. |
| pwa/p2js: | Supported. |
| Example 1: |
sequence s = {"A","B","C","D","E","F","G","H","I","J","K","L"}
puts(1,join_by(s,3,2)) puts(1,"=\n")
-- A D
-- B E
-- C F
--
-- G J
-- H K
-- I L
-- =
puts(1,join_by(s,2,3)) puts(1,"=\n")
-- A C E
-- B D F
--
-- G I K
-- H J L
-- =
puts(1,join_by(s,3,4)) puts(1,"=\n") -- (join_by(s,3,5) same)
-- A D G J
-- B E H K
-- C F I L
-- =
puts(1,join_by(s,4,3)) puts(1,"=\n") -- (join_by(s,4,4) same)
-- A E I
-- B F J
-- C G K
-- D H L
-- =
puts(1,join_by(s,2,5)) puts(1,"=\n") -- (example 5, see the second note)
-- A C E G I
-- B D F H J
--
-- K
-- L
-- =
puts(1,join_by(s,5,2)) puts(1,"=\n") -- (example 6, same as join_by(s,5,3), see last note)
-- A F
-- B G
-- C H
-- D I
-- E J
--
-- K
-- L
-- =
puts(1,join_by(s,1,4)) puts(1,"=\n")
-- A B C D
-- E F G H
-- I J K L
-- =
puts(1,join_by(s,1,6)) puts(1,"=\n")
-- A B C D E F
-- G H I J K L
-- =
puts(1,join_by(s,1,5)) puts(1,"=\n")
-- A B C D E
-- F G H I J
-- K L
-- =
Obviously the puts(1,"=\n") make the output easier to follow: without them, each example starts on a new line, however blank lines only occur mid-example, but not between the examples. In each example above, both the 'A' and the '=' are actually/always the first thing on a new blank line, the "-- " have been added by me. Note how in the "heightwise" (step>1) examples 5 and 6 the trailing (partial) n-blocks retain the step-pattern, as of course does the last "widthwise" (step=1) example. Should you wish to "flatten" the trailing partial block in an otherwise heightwise invocation, I suggest you spilt s into n-wise whole sets and the rest, and invoke join_by twice, with some different step & n on the partial block(s), which could have all manner of desired shapes for the partial>step cases, and therefore it is not really feasible to automate that reliably. In the 6th example, but with n=3, you might want/expect the final K L up in column 3, however the routine as-is cannot do that. Instead, using join_by(s&repeat("",3),5,3) should achieve the desired effect, ie first padding s to a whole multiple of step. There are always going to be some edge cases where length(s) is not a whole multiple of step*n that every man and his dog expects to behave differently, and for that you really need to be prepared to roll your own bespoke version (obvs, copy and rename). |
| Example 2: |
string s = "ABCDEFGHIJKL" puts(1,join_by(s,1,4,"")) puts(1,"=\n") -- ABCD -- EFGH -- IJKL -- = puts(1,join_by(s,1,6,"")) puts(1,"=\n") -- ABCDEF -- GHIJKL -- = As above, I manually inserted the "-- ", and the "=\n" both separate examples and prove there is a '\n' after the 'L'. I should note this splits and re-joins every single individual character, so maybe if you are using join_by() on million-character+ strings it might be noticeably faster to use manual slices in a loop (but test/time to be sure any saving would be worthwhile first). |
| Example 3: | demo/rosetta/IQpuzzle.exw |
| Implementation: |
See builtins\pflatten.e (an autoinclude) for details of the actual implementation. It contains some (lightly tested and) commented-out changes required to automatically output a trailing partial<=step widthwise. There may also be some partial<=(or>)n cases (where that differs from partial<=(or>)step) which merit a subtly different approach, and that is the reason why I said lightly tested and left those changes commented-out. |
| See Also: | join, columnize, shorten |