Skip to content

Commit 994aeee

Browse files
authored
Updates to "Working with Tables" - Adds info on "index renaming" and the table command (#1600)
* Add doc for index-renaming and table command * Fix typos * Fix table literal
1 parent ab17ded commit 994aeee

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

book/working_with_tables.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Working with Tables
22

3+
[[toc]]
4+
5+
## Overview
6+
37
One of the common ways of seeing data in Nu is through a table. Nu comes with a number of commands for working with tables to make it convenient to find what you're looking for, and for narrowing down the data to just what you need.
48

59
To start off, let's get a table that we can use:
@@ -390,3 +394,191 @@ You can also [`reject`](/commands/docs/reject.md) columns in a table by passing
390394
│ 7 │ /mnt │ dir │ │ rwxr-xr-x │ root │ root │ 0 B │
391395
...
392396
```
397+
398+
### The # Index Column
399+
400+
You've noticed that every table, by default, starts with a column with the heading `#`. This column can operate in one of two modes:
401+
402+
1. Internal #
403+
404+
- The default mode
405+
- Nushell provides a 0-based, consecutive index
406+
- Always corresponds to the cell-path row-number, where `select 0` will return the first item in the list, and `select <n-1>` returns the nth item
407+
- Is a display of an internal representation only. In other words, it is not accessible by column name. For example, `get index` will not work, nor `get #`
408+
409+
1. "Index"-Renamed #
410+
411+
- When a column named "index" is created, either directly or as a side-effect of another command, then this `index` column takes the place of the `#` column in the table display. In the table output, the column header is still `#`, but the _name_ of the column is now `index`.
412+
413+
Example:
414+
415+
```nu
416+
ls | each { insert index { 1000 }} | first 5
417+
# => ╭──────┬─────────────────┬──────┬─────────┬──────────────╮
418+
# => │ # │ name │ type │ size │ modified │
419+
# => ├──────┼─────────────────┼──────┼─────────┼──────────────┤
420+
# => │ 1000 │ CNAME │ file │ 15 B │ 9 months ago │
421+
# => │ 1000 │ CONTRIBUTING.md │ file │ 4.3 KiB │ 9 hours ago │
422+
# => │ 1000 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │
423+
# => │ 1000 │ README.md │ file │ 2.2 KiB │ 3 weeks ago │
424+
# => │ 1000 │ assets │ dir │ 4.0 KiB │ 9 months ago │
425+
# => ╰──────┴─────────────────┴──────┴─────────┴──────────────╯
426+
```
427+
428+
- If an `index` key is added to each row in the table, then it can be accessed via `select` and `get`:
429+
430+
```nu
431+
ls | each { insert index { 1000 }} | first 5 | select index name
432+
# => ╭──────┬─────────────────╮
433+
# => │ # │ name │
434+
# => ├──────┼─────────────────┤
435+
# => │ 1000 │ CNAME │
436+
# => │ 1000 │ CONTRIBUTING.md │
437+
# => │ 1000 │ LICENSE │
438+
# => │ 1000 │ README.md │
439+
# => │ 1000 │ assets │
440+
# => ╰──────┴─────────────────╯
441+
```
442+
443+
- On the other hand, if some rows have an `index` key and others don't, the result is no longer a table; it is a `list<any>` due to the different record types:
444+
445+
```nu
446+
ls | upsert 3.index { "--->" } | first 5
447+
# => ╭──────┬─────────────────┬──────┬─────────┬──────────────╮
448+
# => │ # │ name │ type │ size │ modified │
449+
# => ├──────┼─────────────────┼──────┼─────────┼──────────────┤
450+
# => │ 0 │ CNAME │ file │ 15 B │ 9 months ago │
451+
# => │ 1 │ CONTRIBUTING.md │ file │ 4.3 KiB │ 9 hours ago │
452+
# => │ 2 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │
453+
# => │ ---> │ README.md │ file │ 2.2 KiB │ 3 weeks ago │
454+
# => │ 4 │ assets │ dir │ 4.0 KiB │ 9 months ago │
455+
# => ╰──────┴─────────────────┴──────┴─────────┴──────────────╯
456+
457+
ls | upsert 3.index { "--->" } | first 5 | describe
458+
# => list<any> (stream)
459+
460+
ls | upsert 3.index { "--->" } | select index name
461+
# Error: cannot find column 'index'
462+
463+
ls | upsert 3.index { "--->" } | select index? name | first 5
464+
# => ╭──────┬─────────────────╮
465+
# => │ # │ name │
466+
# => ├──────┼─────────────────┤
467+
# => │ │ CNAME │
468+
# => │ │ CONTRIBUTING.md │
469+
# => │ │ LICENSE │
470+
# => │ ---> │ README.md │
471+
# => │ │ assets │
472+
# => ╰──────┴─────────────────╯
473+
```
474+
475+
- As demonstrated in the example above, any rows (records) in the table without an `index` key will continue to display the internal representation.
476+
477+
#### Additional Index Examples
478+
479+
##### Convert # to Index
480+
481+
A useful pattern for converting an internal `#` into an index for all rows, while maintaining the original numbering, is:
482+
483+
```nu
484+
ls | enumerate | flatten
485+
```
486+
487+
While the results _look_ the same, the `index` is now decoupled from the internal cell-path. For example:
488+
489+
```nu
490+
ls | enumerate | flatten | sort-by modified | first 5
491+
# => ╭────┬──────────────┬──────┬─────────┬──────────────╮
492+
# => │ # │ name │ type │ size │ modified │
493+
# => ├────┼──────────────┼──────┼─────────┼──────────────┤
494+
# => │ 0 │ CNAME │ file │ 15 B │ 9 months ago │
495+
# => │ 2 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │
496+
# => │ 4 │ assets │ dir │ 4.0 KiB │ 9 months ago │
497+
# => │ 17 │ lefthook.yml │ file │ 1.1 KiB │ 9 months ago │
498+
# => │ 24 │ snippets │ dir │ 4.0 KiB │ 9 months ago │
499+
# => ╰────┴──────────────┴──────┴─────────┴──────────────╯
500+
501+
ls | enumerate | flatten | sort-by modified | select 4
502+
# => ╭────┬──────────┬──────┬─────────┬──────────────╮
503+
# => │ # │ name │ type │ size │ modified │
504+
# => ├────┼──────────┼──────┼─────────┼──────────────┤
505+
# => │ 24 │ snippets │ dir │ 4.0 KiB │ 9 months ago │
506+
# => ╰────┴──────────┴──────┴─────────┴──────────────╯
507+
```
508+
509+
The `sort-by modified` now _also_ sorts the `index` along with the rest of the columns.
510+
511+
##### Adding a Row Header
512+
513+
```nu
514+
let table = [
515+
[additions deletions delta ];
516+
[ 10 20 -10 ]
517+
[ 15 5 10 ]
518+
[ 8 6 2 ]]
519+
520+
let totals_row = ($table | math sum | insert index {"Totals"})
521+
$table | append $totals_row
522+
# => ╭────────┬───────────┬───────────┬───────╮
523+
# => │ # │ additions │ deletions │ delta │
524+
# => ├────────┼───────────┼───────────┼───────┤
525+
# => │ 0 │ 10 │ 20 │ -10 │
526+
# => │ 1 │ 15 │ 5 │ 10 │
527+
# => │ 2 │ 8 │ 6 │ 2 │
528+
# => │ Totals │ 33 │ 31 │ 2 │
529+
# => ╰────────┴───────────┴───────────┴───────╯
530+
```
531+
532+
### The `table` command
533+
534+
The [`table`](/commands/docs/table.md) command is used to _render_ structured data. This includes:
535+
536+
- Tables
537+
- Lists
538+
- Records
539+
- Ranges
540+
541+
Perhaps contrary to initial assumptions, the result of rendering these types is a `string`. For example:
542+
543+
```nu
544+
[ Nagasaki Ghent Cambridge Izmir Graz Lubango ] | table | describe
545+
# => string (stream)
546+
```
547+
548+
Other data types are passed through the `table` command unchanged.
549+
550+
With no arguments, the output rendered from the `table` command will often _display_ the same as unrendered form. For example:
551+
552+
```nu
553+
[ Nagasaki Ghent Cambridge Izmir Graz Lubango ]
554+
# => ╭───┬───────────╮
555+
# => │ 0 │ Nagasaki │
556+
# => │ 1 │ Ghent │
557+
# => │ 2 │ Cambridge │
558+
# => │ 3 │ Izmir │
559+
# => │ 4 │ Graz │
560+
# => │ 5 │ Lubango │
561+
# => ╰───┴───────────╯
562+
[ Nagasaki Ghent Cambridge Izmir Graz Lubango ] | table
563+
# => ╭───┬───────────╮
564+
# => │ 0 │ Nagasaki │
565+
# => │ 1 │ Ghent │
566+
# => │ 2 │ Cambridge │
567+
# => │ 3 │ Izmir │
568+
# => │ 4 │ Graz │
569+
# => │ 5 │ Lubango │
570+
# => ╰───┴───────────╯
571+
```
572+
573+
This can be useful when you need to store the rendered view of structured data as a string. For example, to remove all ANSI formatting (colors) from a table:
574+
575+
```
576+
ls | table | ansi strip
577+
```
578+
579+
The `table` command also has multiple options for _changing_ the rendering of a table, such as:
580+
581+
- `-e` to expand data that would normally be collapsed when rendering. Compare `scope modules | table` to `scope modules | table -e`.
582+
- `-i false` to hide the `index`/`#` column
583+
- `-a 5` to abbreviate the table to just the first and last 5 entries
584+
- And more

0 commit comments

Comments
 (0)