Convert sum command into subcommand of the math command (#2004)

* Convert sum command into subcommand of the math command

* Add bullet points to math.md documentation
This commit is contained in:
Joseph T. Lyons 2020-06-18 22:02:01 -04:00 committed by GitHub
parent 5f9de80d9b
commit 53a6e9f0bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 175 additions and 143 deletions

View File

@ -352,7 +352,7 @@ pub fn create_default_context(
whole_stream_command(MathMedian),
whole_stream_command(MathMinimum),
whole_stream_command(MathMaximum),
whole_stream_command(Sum),
whole_stream_command(MathSummation),
// File format output
whole_stream_command(To),
whole_stream_command(ToBSON),

View File

@ -102,7 +102,6 @@ pub(crate) mod sort_by;
pub(crate) mod split;
pub(crate) mod split_by;
pub(crate) mod str_;
pub(crate) mod sum;
#[allow(unused)]
pub(crate) mod t_sort_by;
pub(crate) mod table;
@ -199,7 +198,7 @@ pub(crate) use lines::Lines;
pub(crate) use ls::Ls;
#[allow(unused_imports)]
pub(crate) use map_max_by::MapMaxBy;
pub(crate) use math::{Math, MathAverage, MathMaximum, MathMedian, MathMinimum};
pub(crate) use math::{Math, MathAverage, MathMaximum, MathMedian, MathMinimum, MathSummation};
pub(crate) use merge::Merge;
pub(crate) use mkdir::Mkdir;
pub(crate) use mv::Move;
@ -236,7 +235,6 @@ pub(crate) use str_::{
Str, StrCapitalize, StrDowncase, StrFindReplace, StrSet, StrSubstring, StrToDatetime,
StrToDecimal, StrToInteger, StrTrim, StrUpcase,
};
pub(crate) use sum::Sum;
#[allow(unused_imports)]
pub(crate) use t_sort_by::TSortBy;
pub(crate) use table::Table;

View File

@ -56,7 +56,7 @@ impl WholeStreamCommand for Each {
},
Example {
description: "Echo the sum of each row",
example: "echo [[1 2] [3 4]] | each { echo $it | sum }",
example: "echo [[1 2] [3 4]] | each { echo $it | math sum }",
result: Some(vec![
UntaggedValue::int(3).into(),
UntaggedValue::int(7).into(),

View File

@ -22,7 +22,7 @@ impl WholeStreamCommand for SubCommand {
}
fn usage(&self) -> &str {
"Gets the average of a list of numbers"
"Finds the average of a list of numbers or tables"
}
async fn run(
@ -56,7 +56,7 @@ impl WholeStreamCommand for SubCommand {
}
pub fn average(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
let sum = reducer_for(Reduce::Sum);
let sum = reducer_for(Reduce::Summation);
let number = BigDecimal::from_usize(values.len()).ok_or_else(|| {
ShellError::labeled_error(

View File

@ -35,7 +35,7 @@ impl WholeStreamCommand for Command {
mod tests {
use super::*;
use crate::commands::math::{
average::average, max::maximum, min::minimum, utils::MathFunction,
average::average, max::maximum, min::minimum, sum::summation, utils::MathFunction,
};
use nu_plugin::test_helpers::value::{decimal, int};
use nu_protocol::Value;
@ -67,31 +67,41 @@ mod tests {
description: "Single value",
values: vec![int(10)],
expected_err: None,
expected_res: vec![Ok(decimal(10)), Ok(int(10)), Ok(int(10))],
expected_res: vec![Ok(decimal(10)), Ok(int(10)), Ok(int(10)), Ok(int(10))],
},
TestCase {
description: "Multiple Values",
values: vec![int(10), int(30), int(20)],
expected_err: None,
expected_res: vec![Ok(decimal(20)), Ok(int(10)), Ok(int(30))],
expected_res: vec![Ok(decimal(20)), Ok(int(10)), Ok(int(30)), Ok(int(60))],
},
TestCase {
description: "Mixed Values",
values: vec![int(10), decimal(26.5), decimal(26.5)],
expected_err: None,
expected_res: vec![Ok(decimal(21)), Ok(int(10)), Ok(decimal(26.5))],
expected_res: vec![
Ok(decimal(21)),
Ok(int(10)),
Ok(decimal(26.5)),
Ok(decimal(63)),
],
},
TestCase {
description: "Negative Values",
values: vec![int(10), int(-11), int(-14)],
expected_err: None,
expected_res: vec![Ok(decimal(-5)), Ok(int(-14)), Ok(int(10))],
expected_res: vec![Ok(decimal(-5)), Ok(int(-14)), Ok(int(10)), Ok(int(-15))],
},
TestCase {
description: "Mixed Negative Values",
values: vec![int(10), decimal(-11.5), decimal(-13.5)],
expected_err: None,
expected_res: vec![Ok(decimal(-5)), Ok(decimal(-13.5)), Ok(int(10))],
expected_res: vec![
Ok(decimal(-5)),
Ok(decimal(-13.5)),
Ok(int(10)),
Ok(decimal(-15)),
],
},
// TODO-Uncomment once I figure out how to structure tables
// TestCase {
@ -116,7 +126,7 @@ mod tests {
for tc in tt.iter() {
let tc: &TestCase = tc; // Just for type annotations
let math_functions: Vec<MathFunction> = vec![average, minimum, maximum];
let math_functions: Vec<MathFunction> = vec![average, minimum, maximum, summation];
let results = math_functions
.iter()
.map(|mf| mf(&tc.values, &test_tag))

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
}
fn usage(&self) -> &str {
"Get the maximum of a list of numbers or tables"
"Finds the maximum within a list of numbers or tables"
}
async fn run(

View File

@ -121,7 +121,7 @@ pub fn median(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
fn compute_average(values: &[Value], name: impl Into<Tag>) -> Result<Value, ShellError> {
let name = name.into();
let sum = reducer_for(Reduce::Sum);
let sum = reducer_for(Reduce::Summation);
let number = BigDecimal::from_usize(2).ok_or_else(|| {
ShellError::labeled_error(
"could not convert to big decimal",

View File

@ -3,6 +3,7 @@ pub mod command;
pub mod max;
pub mod median;
pub mod min;
pub mod sum;
pub mod utils;
pub use average::SubCommand as MathAverage;
@ -10,3 +11,4 @@ pub use command::Command as Math;
pub use max::SubCommand as MathMaximum;
pub use median::SubCommand as MathMedian;
pub use min::SubCommand as MathMinimum;
pub use sum::SubCommand as MathSummation;

View File

@ -1,26 +1,25 @@
use crate::commands::math::utils::calculate;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce};
use nu_errors::ShellError;
use nu_protocol::{Dictionary, ReturnSuccess, Signature, UntaggedValue, Value};
use nu_protocol::{Dictionary, Signature, UntaggedValue, Value};
use num_traits::identities::Zero;
use indexmap::map::IndexMap;
pub struct Sum;
pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for Sum {
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"sum"
"math sum"
}
fn signature(&self) -> Signature {
Signature::build("sum")
Signature::build("math sum")
}
fn usage(&self) -> &str {
"Sums the values."
"Finds the sum of a list of numbers or tables"
}
async fn run(
@ -28,16 +27,19 @@ impl WholeStreamCommand for Sum {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
sum(RunnableContext {
input: args.input,
registry: registry.clone(),
shell_manager: args.shell_manager,
host: args.host,
ctrl_c: args.ctrl_c,
current_errors: args.current_errors,
name: args.call_info.name_tag,
raw_input: args.raw_input,
})
calculate(
RunnableContext {
input: args.input,
registry: registry.clone(),
shell_manager: args.shell_manager,
host: args.host,
ctrl_c: args.ctrl_c,
current_errors: args.current_errors,
name: args.call_info.name_tag,
raw_input: args.raw_input,
},
summation,
)
.await
}
@ -45,31 +47,28 @@ impl WholeStreamCommand for Sum {
vec![
Example {
description: "Sum a list of numbers",
example: "echo [1 2 3] | sum",
example: "echo [1 2 3] | math sum",
result: Some(vec![UntaggedValue::int(6).into()]),
},
Example {
description: "Get the disk usage for the current directory",
example: "ls --all --du | get size | sum",
example: "ls --all --du | get size | math sum",
result: None,
},
]
}
}
async fn sum(
RunnableContext { mut input, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
let values: Vec<Value> = input.drain_vec().await;
let action = reducer_for(Reduce::Sum);
pub fn summation(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
let sum = reducer_for(Reduce::Summation);
if values.iter().all(|v| v.is_primitive()) {
let total = action(Value::zero(), values)?;
Ok(OutputStream::one(ReturnSuccess::value(total)))
Ok(sum(Value::zero(), values.to_vec())?)
} else {
let mut column_values = IndexMap::new();
for value in values {
if let UntaggedValue::Row(row_dict) = value.value {
if let UntaggedValue::Row(row_dict) = value.value.clone() {
for (key, value) in row_dict.entries.iter() {
column_values
.entry(key.clone())
@ -80,32 +79,28 @@ async fn sum(
}
let mut column_totals = IndexMap::new();
for (col_name, col_vals) in column_values {
let sum = action(Value::zero(), col_vals);
match sum {
Ok(value) => {
column_totals.insert(col_name, value);
}
Err(err) => return Err(err),
};
let sum = sum(Value::zero(), col_vals)?;
column_totals.insert(col_name, sum);
}
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(Dictionary {
entries: column_totals,
})
.into_untagged_value(),
)))
Ok(UntaggedValue::Row(Dictionary {
entries: column_totals,
})
.into_value(name))
}
}
#[cfg(test)]
mod tests {
use super::Sum;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Sum {})
test_examples(SubCommand {})
}
}

View File

@ -288,14 +288,14 @@ pub fn reducer_for(
command: Reduce,
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
match command {
Reduce::Sum | Reduce::Default => Box::new(formula(Value::zero(), Box::new(sum))),
Reduce::Summation | Reduce::Default => Box::new(formula(Value::zero(), Box::new(sum))),
Reduce::Minimum => Box::new(|_, values| min(values)),
Reduce::Maximum => Box::new(|_, values| max(values)),
}
}
pub enum Reduce {
Sum,
Summation,
Minimum,
Maximum,
Default,
@ -309,7 +309,7 @@ pub fn reduce(
let tag = tag.into();
let reduce_with = match reducer {
Some(cmd) if cmd == "sum" => reducer_for(Reduce::Sum),
Some(cmd) if cmd == "sum" => reducer_for(Reduce::Summation),
Some(cmd) if cmd == "min" => reducer_for(Reduce::Minimum),
Some(cmd) if cmd == "max" => reducer_for(Reduce::Maximum),
Some(_) | None => reducer_for(Reduce::Default),
@ -642,7 +642,7 @@ mod tests {
fn reducer_computes_given_a_sum_command() -> Result<(), ShellError> {
let subject = vec![int(1), int(1), int(1)];
let action = reducer_for(Reduce::Sum);
let action = reducer_for(Reduce::Summation);
assert_eq!(action(Value::zero(), subject)?, int(3));

View File

@ -4,7 +4,7 @@ use nu_test_support::nu;
fn drop_rows() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"echo '[{"foo": 3}, {"foo": 8}, {"foo": 4}]' | from json | drop 2 | get foo | sum | echo $it"#
r#"echo '[{"foo": 3}, {"foo": 8}, {"foo": 4}]' | from json | drop 2 | get foo | math sum | echo $it"#
);
assert_eq!(actual.out, "3");

View File

@ -5,7 +5,7 @@ fn each_works_separately() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
echo [1 2 3] | each { echo $it 10 | sum } | to json | echo $it
echo [1 2 3] | each { echo $it 10 | math sum } | to json | echo $it
"#
));

View File

@ -22,7 +22,7 @@ fn adds_value_provided_if_column_is_empty() {
open likes.csv
| empty? likes 1
| get likes
| sum
| math sum
| echo $it
"#
));
@ -43,7 +43,7 @@ fn adds_value_provided_for_columns_that_are_empty() {
{"boost": 1, "check": {}},
{"boost": null, "check": ["" {} [] ""]}
]
"#,
)]);
@ -53,7 +53,7 @@ fn adds_value_provided_for_columns_that_are_empty() {
open checks.json
| empty? boost check 1
| get boost check
| sum
| math sum
| echo $it
"#
));

View File

@ -22,7 +22,7 @@ fn rows() {
open caballeros.csv
| keep 3
| get lucky_code
| sum
| math sum
| echo $it
"#
));

View File

@ -41,7 +41,7 @@ fn condition_is_met() {
| keep-until "Chicken Collection" == "Red Chickens"
| str to-int "31/04/2020"
| get "31/04/2020"
| sum
| math sum
| echo $it
"#
));

View File

@ -41,7 +41,7 @@ fn condition_is_met() {
| keep-while "Chicken Collection" != "Blue Chickens"
| str to-int "31/04/2020"
| get "31/04/2020"
| sum
| math sum
| echo $it
"#
));

View File

@ -33,7 +33,7 @@ fn row() {
| merge { open new_caballeros.csv }
| where country in: ["Guayaquil Ecuador" "New Zealand"]
| get luck
| sum
| math sum
| echo $it
"#
));

View File

@ -40,7 +40,7 @@ fn condition_is_met() {
| skip-until "Chicken Collection" == "Red Chickens"
| str to-int "31/04/2020"
| get "31/04/2020"
| sum
| math sum
| echo $it
"#
));

View File

@ -108,7 +108,7 @@ fn converts_to_decimal() {
echo "3.1, 0.0415"
| split row ","
| str to-decimal
| sum
| math sum
"#
));
@ -130,7 +130,7 @@ fn sets() {
cwd: dirs.test(), pipeline(
r#"
open sample.toml
| str set wykittenshell package.name
| str set wykittenshell package.name
| get package.name
| echo $it
"#

View File

@ -25,7 +25,7 @@ fn all() {
open meals.json
| get meals
| get calories
| sum
| math sum
| echo $it
"#
));
@ -53,7 +53,7 @@ fn outputs_zero_with_no_input() {
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
sum
math sum
| echo $it
"#
));
@ -74,7 +74,7 @@ fn compute_sum_of_individual_row() -> Result<(), String> {
for (column_name, expected_value) in answers_for_columns.iter() {
let actual = nu!(
cwd: "tests/fixtures/formats/",
format!("open sample-ps-output.json | select {} | sum | get {}", column_name, column_name)
format!("open sample-ps-output.json | select {} | math sum | get {}", column_name, column_name)
);
let result =
f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?;
@ -95,7 +95,7 @@ fn compute_sum_of_table() -> Result<(), String> {
for (column_name, expected_value) in answers_for_columns.iter() {
let actual = nu!(
cwd: "tests/fixtures/formats/",
format!("open sample-ps-output.json | select cpu mem virtual | sum | get {}", column_name)
format!("open sample-ps-output.json | select cpu mem virtual | math sum | get {}", column_name)
);
let result =
f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?;
@ -108,7 +108,7 @@ fn compute_sum_of_table() -> Result<(), String> {
fn sum_of_a_row_containing_a_table_is_an_error() {
let actual = nu!(
cwd: "tests/fixtures/formats/",
"open sample-sys-output.json | sum"
"open sample-sys-output.json | math sum"
);
assert!(actual
.err

View File

@ -14,7 +14,7 @@ fn filters_by_unit_size_comparison() {
fn filters_with_nothing_comparison() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"echo '[{"foo": 3}, {"foo": null}, {"foo": 4}]' | from json | get foo | compact | where $it > 1 | sum | echo $it"#
r#"echo '[{"foo": 3}, {"foo": null}, {"foo": 4}]' | from json | get foo | compact | where $it > 1 | math sum | echo $it"#
);
assert_eq!(actual.out, "7");
@ -24,7 +24,7 @@ fn filters_with_nothing_comparison() {
fn where_in_table() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name in: ["foo"] | get size | sum | echo $it"#
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name in: ["foo"] | get size | math sum | echo $it"#
);
assert_eq!(actual.out, "5");
@ -34,7 +34,7 @@ fn where_in_table() {
fn where_not_in_table() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name not-in: ["foo"] | get size | sum | echo $it"#
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name not-in: ["foo"] | get size | math sum | echo $it"#
);
assert_eq!(actual.out, "4");

View File

@ -36,14 +36,14 @@ mod tests {
| from-csv
| get rusty_luck
| str --to-int
| sum
| math sum
| echo "$it"
"#,
);
assert_eq!(
actual,
r#"open los_tres_amigos.txt | from-csv | get rusty_luck | str --to-int | sum | echo "$it""#
r#"open los_tres_amigos.txt | from-csv | get rusty_luck | str --to-int | math sum | echo "$it""#
);
}
}

View File

@ -1,95 +1,126 @@
# math
Mathematical functions that generally only operate on a list of numbers (integers, decimals, bytes) and tables.
Currently the following functions are implemented:
`math average` Get the average of a list of number
`math min` Get the minimum of a list of numbers
`math max` Get the maximum of a list of numbers
* `math average`: Finds the average of a list of numbers or tables
* `math min`: Finds the minimum within a list of numbers or tables
* `math max`: Finds the maximum within a list of numbers or tables
* `math sum`: Finds the sum of a list of numbers or tables
However, the mathematical functions like `min` and `max` are more permissive and also work on `Dates`.
## Examples
To get the average of the file sizes in a directory, simply pipe the size column from the ls command to the average command.
### List of Numbers (Integers, Decimals, Bytes)
```shell
> ls
# │ name │ type │ size │ modified
# │ name │ type │ size │ modified
────┼────────────────────┼──────┼──────────┼─────────────
0 │ CODE_OF_CONDUCT.md │ File │ 3.4 KB │ 4 days ago
1 │ CONTRIBUTING.md │ File │ 1.3 KB │ 4 days ago
2 │ Cargo.lock │ File │ 106.3 KB │ 6 mins ago
3 │ Cargo.toml │ File │ 4.6 KB │ 3 days ago
4 │ LICENSE │ File │ 1.1 KB │ 4 days ago
5 │ Makefile.toml │ File │ 449 B │ 4 days ago
6 │ README.md │ File │ 16.0 KB │ 6 mins ago
7 │ TODO.md │ File │ 0 B │ 6 mins ago
8 │ assets │ Dir │ 128 B │ 4 days ago
9 │ build.rs │ File │ 78 B │ 4 days ago
10 │ crates │ Dir │ 672 B │ 3 days ago
11 │ debian │ Dir │ 352 B │ 4 days ago
12 │ docker │ Dir │ 288 B │ 4 days ago
13 │ docs │ Dir │ 160 B │ 4 days ago
14 │ features.toml │ File │ 632 B │ 4 days ago
15 │ images │ Dir │ 160 B │ 4 days ago
16 │ justfile │ File │ 234 B │ 3 days ago
17 │ rustfmt.toml │ File │ 16 B │ 4 days ago
18 │ src │ Dir │ 128 B │ 4 days ago
19 │ target │ Dir │ 192 B │ 8 hours ago
20 │ tests │ Dir │ 192 B │ 4 days ago
0 │ CODE_OF_CONDUCT.md │ File │ 3.4 KB │ 4 days ago
1 │ CONTRIBUTING.md │ File │ 1.3 KB │ 4 days ago
2 │ Cargo.lock │ File │ 106.3 KB │ 6 mins ago
3 │ Cargo.toml │ File │ 4.6 KB │ 3 days ago
4 │ LICENSE │ File │ 1.1 KB │ 4 days ago
5 │ Makefile.toml │ File │ 449 B │ 4 days ago
6 │ README.md │ File │ 16.0 KB │ 6 mins ago
7 │ TODO.md │ File │ 0 B │ 6 mins ago
8 │ assets │ Dir │ 128 B │ 4 days ago
9 │ build.rs │ File │ 78 B │ 4 days ago
10 │ crates │ Dir │ 672 B │ 3 days ago
11 │ debian │ Dir │ 352 B │ 4 days ago
12 │ docker │ Dir │ 288 B │ 4 days ago
13 │ docs │ Dir │ 160 B │ 4 days ago
14 │ features.toml │ File │ 632 B │ 4 days ago
15 │ images │ Dir │ 160 B │ 4 days ago
16 │ justfile │ File │ 234 B │ 3 days ago
17 │ rustfmt.toml │ File │ 16 B │ 4 days ago
18 │ src │ Dir │ 128 B │ 4 days ago
19 │ target │ Dir │ 192 B │ 8 hours ago
20 │ tests │ Dir │ 192 B │ 4 days ago
```
```shell
> ls | get size | math average
───┬────────
0 │ 6.5 KB
0 │ 7.2 KB
───┴────────
```
```shell
> ls | get size | math min
───┬─────
0 │ 0 B
0 │ 0 B
───┴─────
```
```shell
> ls | get size | math max
───┬──────────
0 │ 106.3 KB
0 │ 113.5 KB
───┴──────────
```
# Dates
```shell
> ls | get size | math sum
───┬──────────
0 │ 143.4 KB
───┴──────────
```
### Dates
```shell
> ls | get modified | math min
2020-06-09 17:25:51.798743222 UTC
```
```shell
> ls | get modified | math max
2020-06-14 05:49:59.637449186 UT
```
### Operations on tables
```shell
> pwd | split row / | size
───┬───────┬───────┬───────┬────────────
# │ lines │ words │ chars │ max length
───┼───────┼───────┼───────┼────────────
0 │ 0 │ 1 │ 5 │ 5
1 │ 0 │ 1 │ 7 │ 7
2 │ 0 │ 1 │ 9 │ 9
3 │ 0 │ 1 │ 7 │ 7
───┴───────┴───────┴───────┴────────────
```shell
> pwd | split row / | size
───┬───────┬───────┬───────┬────────────
# │ lines │ words │ chars │ max length
───┼───────┼───────┼───────┼────────────
0 │ 0 │ 1 │ 5 │ 5
1 │ 0 │ 1 │ 7 │ 7
2 │ 0 │ 1 │ 9 │ 9
3 │ 0 │ 1 │ 7 │ 7
───┴───────┴───────┴───────┴────────────
```
```shell
> pwd | split row / | size | math max
───────────┬───
lines │ 0
words │ 1
chars │ 9
max length │ 9
lines │ 0
words │ 1
chars │ 9
max length │ 9
────────────┴───
```
```shell
> pwd | split row / | size | math average
────────────┬────────
lines │ 0.0000
words │ 1.0000
chars │ 7.0000
max length │ 7.0000
lines │ 0.0000
words │ 1.0000
chars │ 7.0000
max length │ 7.0000
────────────┴────────
```
## Errors
`math` functions are aggregation functions so empty lists are invalid
```shell
> echo [] | math average
error: Error: Unexpected: Cannot perform aggregate math operation on empty data
@ -102,7 +133,3 @@ then unexpected results can occur.
> echo [1 2 a ] | math average
0
```

View File

@ -41,7 +41,7 @@ Applies the subcommand to a value or a table.
1 │ │ filesystem │
━━━┷━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
> echo "1, 2, 3" | split row "," | str to-int | sum
> echo "1, 2, 3" | split row "," | str to-int | math sum
━━━━━━━━━
<value>
─────────

View File

@ -5,7 +5,7 @@ This command allows you to calculate the sum of values in a column.
To get the sum of the file sizes in a directory, simply pipe the size column from the ls command to the sum command.
```shell
> ls | get size | sum
> ls | get size | math sum
━━━━━━━━━
value
━━━━━━━━━
@ -15,7 +15,7 @@ To get the sum of the file sizes in a directory, simply pipe the size column fro
To get the sum of the characters that make up your present working directory.
```shell
> pwd | split-row / | size | get chars | sum
> pwd | split-row / | size | get chars | math sum
━━━━━━━━━
<value>
━━━━━━━━━
@ -27,15 +27,15 @@ Note that sum only works for integer and byte values. If the shell doesn't recog
One way to solve this is to convert each row to an integer when possible and then pipe the result to `sum`
```shell
> open tests/fixtures/formats/caco3_plastics.csv | get tariff_item | sum
> open tests/fixtures/formats/caco3_plastics.csv | get tariff_item | math sum
error: Unrecognized type in stream: Primitive(String("2509000000"))
- shell:1:0
1 | open tests/fixtures/formats/caco3_plastics.csv | get tariff_item | sum
1 | open tests/fixtures/formats/caco3_plastics.csv | get tariff_item | math sum
| ^^^^ source
```
```shell
> open tests/fixtures/formats/caco3_plastics.csv | get tariff_item | str --to-int | sum
> open tests/fixtures/formats/caco3_plastics.csv | get tariff_item | str --to-int | math sum
━━━━━━━━━━━━━
<value>
─────────────

View File

@ -198,7 +198,7 @@ fn echoing_ranges() {
let actual = nu!(
cwd: ".",
r#"
echo 1..3 | sum
echo 1..3 | math sum
"#
);