diff --git a/stdlib-candidate/std-rfc/conversions/columns-into-table.nu b/stdlib-candidate/std-rfc/conversions/columns-into-table.nu new file mode 100644 index 0000000..380d180 --- /dev/null +++ b/stdlib-candidate/std-rfc/conversions/columns-into-table.nu @@ -0,0 +1,31 @@ +# Convert a list of columns into a table +# +# Examples: +# +# [ +# ([ 1 2 3 ] | wrap a) +# ([ 4 5 6 ] | wrap b) +# ([ 7 8 9 ] | wrap c) +# ] | columns-into-table +# => ╭───┬───┬───┬───╮ +# => │ # │ a │ b │ c │ +# => ├───┼───┼───┼───┤ +# => │ 0 │ 1 │ 4 │ 7 │ +# => │ 1 │ 2 │ 5 │ 8 │ +# => │ 2 │ 3 │ 6 │ 9 │ +# => ╰───┴───┴───┴───╯ +# +# Can roundtrip with `table-into-columns` +# +# ls | table-into-columns | columns-into-table +# => ╭───┬────────────────────────┬──────┬────────┬────────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├───┼────────────────────────┼──────┼────────┼────────────────┤ +# => │ 0 │ into-list.nu │ file │ 378 B │ 40 minutes ago │ +# => │ 1 │ mod.nu │ file │ 28 B │ 41 minutes ago │ +# => │ 2 │ name-values.nu │ file │ 394 B │ 34 minutes ago │ +# => │ 3 │ record-into-columns.nu │ file │ 1.3 kB │ 27 minutes ago │ +# => ╰───┴────────────────────────┴──────┴────────┴────────────────╯ +export def main []: [list -> table] { + reduce {|it| merge $it} +} diff --git a/stdlib-candidate/std-rfc/conversions/into.nu b/stdlib-candidate/std-rfc/conversions/into-list.nu similarity index 79% rename from stdlib-candidate/std-rfc/conversions/into.nu rename to stdlib-candidate/std-rfc/conversions/into-list.nu index fe859ca..6d65975 100644 --- a/stdlib-candidate/std-rfc/conversions/into.nu +++ b/stdlib-candidate/std-rfc/conversions/into-list.nu @@ -1,7 +1,6 @@ # Convert a Nushell value to a list # -# Primary useful for range-to-list, -# but other types are accepted as well. +# Primary useful for range-to-list, but other types are accepted as well. # # Example: # @@ -15,4 +14,4 @@ export def "into list" []: any -> list { table => $input _ => [ $input ] } -} \ No newline at end of file +} diff --git a/stdlib-candidate/std-rfc/conversions/mod.nu b/stdlib-candidate/std-rfc/conversions/mod.nu index fe7b611..066f0b0 100644 --- a/stdlib-candidate/std-rfc/conversions/mod.nu +++ b/stdlib-candidate/std-rfc/conversions/mod.nu @@ -1 +1,5 @@ -export use ./into.nu * \ No newline at end of file +export use ./into-list.nu * +export use ./columns-into-table.nu * +export use ./name-values.nu * +export use ./record-into-columns.nu * +export use ./table-into-columns.nu * diff --git a/stdlib-candidate/std-rfc/conversions/name-values.nu b/stdlib-candidate/std-rfc/conversions/name-values.nu new file mode 100644 index 0000000..d4c664e --- /dev/null +++ b/stdlib-candidate/std-rfc/conversions/name-values.nu @@ -0,0 +1,14 @@ +# Assign keynames to a list of values, effectively converting the list to a record. +# +# Example: +# +# [ 1 2 3 ] | name-values a b c +# => ╭───┬───╮ +# => │ a │ 1 │ +# => │ b │ 2 │ +# => │ c │ 3 │ +# => ╰───┴───╯ +export def main [...names: string]: [list -> record] { + let IN = $in + 0.. | zip $IN | into record | rename ...$names +} diff --git a/stdlib-candidate/std-rfc/conversions/record-into-columns.nu b/stdlib-candidate/std-rfc/conversions/record-into-columns.nu new file mode 100644 index 0000000..4c6b3dd --- /dev/null +++ b/stdlib-candidate/std-rfc/conversions/record-into-columns.nu @@ -0,0 +1,34 @@ +# Convert a record, where each value is a list, into a list of columns. +# { a: [ 1 2 3 ], b: [ 4 5 6 ] } | record-into-columns +# => ╭───┬───────────╮ +# => │ 0 │ ╭───┬───╮ │ +# => │ │ │ # │ a │ │ +# => │ │ ├───┼───┤ │ +# => │ │ │ 0 │ 1 │ │ +# => │ │ │ 1 │ 2 │ │ +# => │ │ │ 2 │ 3 │ │ +# => │ │ ╰───┴───╯ │ +# => │ 1 │ ╭───┬───╮ │ +# => │ │ │ # │ b │ │ +# => │ │ ├───┼───┤ │ +# => │ │ │ 0 │ 4 │ │ +# => │ │ │ 1 │ 5 │ │ +# => │ │ │ 2 │ 6 │ │ +# => │ │ ╰───┴───╯ │ +# => ╰───┴───────────╯ +# => +# This can be especially useful when combined with `columns-into-table`, as in: +# +# { a: [ 1 2 3 ], b: [ 4 5 6 ] } | record-into-columns +# | columns-into-table +# => ╭───┬───┬───╮ +# => │ # │ a │ b │ +# => ├───┼───┼───┤ +# => │ 0 │ 1 │ 4 │ +# => │ 1 │ 2 │ 5 │ +# => │ 2 │ 3 │ 6 │ +# => ╰───┴───┴───╯ +# => +export def main []: [record -> list] { + items {|key, val| $val | wrap $key} +} diff --git a/stdlib-candidate/std-rfc/conversions/table-into-columns.nu b/stdlib-candidate/std-rfc/conversions/table-into-columns.nu new file mode 100644 index 0000000..d9b9394 --- /dev/null +++ b/stdlib-candidate/std-rfc/conversions/table-into-columns.nu @@ -0,0 +1,21 @@ +# Convert/split a table into a list of columns +# +# Examples: +# ls | table-into-columns +# => Returns a list of 4 tables, one for each of the `ls` columns +# +# Can be roundtripped with `columns-into-table` +# +# ls | table-into-columns | columns-into-table +# => ╭───┬────────────────────────┬──────┬────────┬────────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├───┼────────────────────────┼──────┼────────┼────────────────┤ +# => │ 0 │ into-list.nu │ file │ 378 B │ 40 minutes ago │ +# => │ 1 │ mod.nu │ file │ 28 B │ 41 minutes ago │ +# => │ 2 │ name-values.nu │ file │ 394 B │ 34 minutes ago │ +# => │ 3 │ record-into-columns.nu │ file │ 1.3 kB │ 27 minutes ago │ +# => ╰───┴────────────────────────┴──────┴────────┴────────────────╯ +export def main []: [table -> list
] { + let IN = $in + $IN | columns | each {|col| $IN | select $col} +} diff --git a/stdlib-candidate/std-rfc/tables/col-indices.nu b/stdlib-candidate/std-rfc/tables/col-indices.nu index 02f9d04..202d413 100644 --- a/stdlib-candidate/std-rfc/tables/col-indices.nu +++ b/stdlib-candidate/std-rfc/tables/col-indices.nu @@ -1,4 +1,4 @@ -use ../conversions/into.nu * +use ../conversions/into-list.nu * use ./select-ranges.nu * export def main [ ...ranges ] { @@ -12,4 +12,4 @@ export def main [ ...ranges ] { $in | columns | select ranges $indices | get item -} \ No newline at end of file +} diff --git a/stdlib-candidate/std-rfc/tables/reject-ranges.nu b/stdlib-candidate/std-rfc/tables/reject-ranges.nu index 802bc48..87fa45e 100644 --- a/stdlib-candidate/std-rfc/tables/reject-ranges.nu +++ b/stdlib-candidate/std-rfc/tables/reject-ranges.nu @@ -1,10 +1,8 @@ use ./row-indices.nu * -# Rejects one or more rows while keeping -# the original indices. +# Rejects one or more rows while keeping the original indices. # -# Example - Rejects the first, fifth, and -# sixth rows from the table: +# Example - Rejects the first, fifth, and sixth rows from the table: # # ls / | reject ranges 0 4..5 export def "reject ranges" [ ...ranges ] { diff --git a/stdlib-candidate/std-rfc/tables/row-indices.nu b/stdlib-candidate/std-rfc/tables/row-indices.nu index c153d12..d8f3bf3 100644 --- a/stdlib-candidate/std-rfc/tables/row-indices.nu +++ b/stdlib-candidate/std-rfc/tables/row-indices.nu @@ -1,9 +1,6 @@ -use ../conversions/into.nu * +use ../conversions/into-list.nu * -# Return a list of indices -# for the provided ranges or indices. -# Primarily used as a helper for -# "select ranges" et. al. +# Return a list of indices for the provided ranges or indices. Primarily used as a helper for "select ranges" et. al. # # Example: # @@ -22,4 +19,4 @@ export def main [ ...ranges ] { | reduce -f [] {|range,indices| $indices ++ ($range | into list) } -} \ No newline at end of file +} diff --git a/stdlib-candidate/std-rfc/tables/select-ranges.nu b/stdlib-candidate/std-rfc/tables/select-ranges.nu index 967c79d..a3fe9f2 100644 --- a/stdlib-candidate/std-rfc/tables/select-ranges.nu +++ b/stdlib-candidate/std-rfc/tables/select-ranges.nu @@ -1,10 +1,8 @@ use ./row-indices.nu * -# Selects one or more rows while keeping -# the original indices. +# Selects one or more rows while keeping the original indices. # -# Example - Selects the first, fifth, and -# sixth rows from the table: +# Example - Selects the first, fifth, and sixth rows from the table: # # ls / | select ranges 0 4..5 # @@ -13,10 +11,8 @@ use ./row-indices.nu * # ls / | select 5 # # Example - Select the 4th row. -# Note that the difference between this -# and `select 3` is that the index (#) -# column shows the *original* (pre-select) -# position in the table. +# +# Note that the difference between this and `select 3` is that the index (#) column shows the *original* (pre-select) position in the table. # # ls | select ranges 3 export def "select ranges" [ ...ranges ] { diff --git a/stdlib-candidate/tests/conversions.nu b/stdlib-candidate/tests/conversions.nu index 003d28c..04124f4 100644 --- a/stdlib-candidate/tests/conversions.nu +++ b/stdlib-candidate/tests/conversions.nu @@ -46,3 +46,65 @@ def list-into-list [] { ) } + +#[test] +def table-into-columns--roundtrip [] { + assert equal ( + ls + ) ( + ls | table-into-columns | columns-into-table + ) +} + +const test_record_of_lists = { + a: [ 1 2 3 ] + b: [ 4 5 6 ] +} + +#[test] +def record-into-columns--simple [] { + let actual = ( + $test_record_of_lists + | record-into-columns + | get 1.b.2 + ) + + let expected = 6 + + assert equal $actual $expected +} + +#[test] +def table-into-columns--simple [] { + let actual = ( + ls | table-into-columns | get 1 | columns | get 0 + ) + let expected = 'type' + + assert equal $actual $expected +} + +#[test] +def name-values--simple [] { + let actual = ( + [ 1 2 3 ] | name-values one two three + | get 'two' + ) + + let expected = 2 + + assert equal $actual $expected +} + +#[test] +def name-values--missing-keyname [] { + let actual = ( + [ 1 2 3 ] | name-values one two + | columns + ) + + # Column/key names are strings, even those that came from the index ('2') + let expected = [ 'one' 'two' '2' ] + + assert equal $actual $expected +}