mirror of
https://github.com/nushell/nushell.git
synced 2025-02-16 10:32:29 +01:00
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:
parent
5f9de80d9b
commit
53a6e9f0bd
@ -352,7 +352,7 @@ pub fn create_default_context(
|
|||||||
whole_stream_command(MathMedian),
|
whole_stream_command(MathMedian),
|
||||||
whole_stream_command(MathMinimum),
|
whole_stream_command(MathMinimum),
|
||||||
whole_stream_command(MathMaximum),
|
whole_stream_command(MathMaximum),
|
||||||
whole_stream_command(Sum),
|
whole_stream_command(MathSummation),
|
||||||
// File format output
|
// File format output
|
||||||
whole_stream_command(To),
|
whole_stream_command(To),
|
||||||
whole_stream_command(ToBSON),
|
whole_stream_command(ToBSON),
|
||||||
|
@ -102,7 +102,6 @@ pub(crate) mod sort_by;
|
|||||||
pub(crate) mod split;
|
pub(crate) mod split;
|
||||||
pub(crate) mod split_by;
|
pub(crate) mod split_by;
|
||||||
pub(crate) mod str_;
|
pub(crate) mod str_;
|
||||||
pub(crate) mod sum;
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub(crate) mod t_sort_by;
|
pub(crate) mod t_sort_by;
|
||||||
pub(crate) mod table;
|
pub(crate) mod table;
|
||||||
@ -199,7 +198,7 @@ pub(crate) use lines::Lines;
|
|||||||
pub(crate) use ls::Ls;
|
pub(crate) use ls::Ls;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub(crate) use map_max_by::MapMaxBy;
|
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 merge::Merge;
|
||||||
pub(crate) use mkdir::Mkdir;
|
pub(crate) use mkdir::Mkdir;
|
||||||
pub(crate) use mv::Move;
|
pub(crate) use mv::Move;
|
||||||
@ -236,7 +235,6 @@ pub(crate) use str_::{
|
|||||||
Str, StrCapitalize, StrDowncase, StrFindReplace, StrSet, StrSubstring, StrToDatetime,
|
Str, StrCapitalize, StrDowncase, StrFindReplace, StrSet, StrSubstring, StrToDatetime,
|
||||||
StrToDecimal, StrToInteger, StrTrim, StrUpcase,
|
StrToDecimal, StrToInteger, StrTrim, StrUpcase,
|
||||||
};
|
};
|
||||||
pub(crate) use sum::Sum;
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub(crate) use t_sort_by::TSortBy;
|
pub(crate) use t_sort_by::TSortBy;
|
||||||
pub(crate) use table::Table;
|
pub(crate) use table::Table;
|
||||||
|
@ -56,7 +56,7 @@ impl WholeStreamCommand for Each {
|
|||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Echo the sum of each row",
|
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![
|
result: Some(vec![
|
||||||
UntaggedValue::int(3).into(),
|
UntaggedValue::int(3).into(),
|
||||||
UntaggedValue::int(7).into(),
|
UntaggedValue::int(7).into(),
|
||||||
|
@ -22,7 +22,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
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(
|
async fn run(
|
||||||
@ -56,7 +56,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn average(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
|
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(|| {
|
let number = BigDecimal::from_usize(values.len()).ok_or_else(|| {
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
|
@ -35,7 +35,7 @@ impl WholeStreamCommand for Command {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::commands::math::{
|
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_plugin::test_helpers::value::{decimal, int};
|
||||||
use nu_protocol::Value;
|
use nu_protocol::Value;
|
||||||
@ -67,31 +67,41 @@ mod tests {
|
|||||||
description: "Single value",
|
description: "Single value",
|
||||||
values: vec![int(10)],
|
values: vec![int(10)],
|
||||||
expected_err: None,
|
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 {
|
TestCase {
|
||||||
description: "Multiple Values",
|
description: "Multiple Values",
|
||||||
values: vec![int(10), int(30), int(20)],
|
values: vec![int(10), int(30), int(20)],
|
||||||
expected_err: None,
|
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 {
|
TestCase {
|
||||||
description: "Mixed Values",
|
description: "Mixed Values",
|
||||||
values: vec![int(10), decimal(26.5), decimal(26.5)],
|
values: vec![int(10), decimal(26.5), decimal(26.5)],
|
||||||
expected_err: None,
|
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 {
|
TestCase {
|
||||||
description: "Negative Values",
|
description: "Negative Values",
|
||||||
values: vec![int(10), int(-11), int(-14)],
|
values: vec![int(10), int(-11), int(-14)],
|
||||||
expected_err: None,
|
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 {
|
TestCase {
|
||||||
description: "Mixed Negative Values",
|
description: "Mixed Negative Values",
|
||||||
values: vec![int(10), decimal(-11.5), decimal(-13.5)],
|
values: vec![int(10), decimal(-11.5), decimal(-13.5)],
|
||||||
expected_err: None,
|
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
|
// TODO-Uncomment once I figure out how to structure tables
|
||||||
// TestCase {
|
// TestCase {
|
||||||
@ -116,7 +126,7 @@ mod tests {
|
|||||||
|
|
||||||
for tc in tt.iter() {
|
for tc in tt.iter() {
|
||||||
let tc: &TestCase = tc; // Just for type annotations
|
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
|
let results = math_functions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mf| mf(&tc.values, &test_tag))
|
.map(|mf| mf(&tc.values, &test_tag))
|
||||||
|
@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
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(
|
async fn run(
|
||||||
|
@ -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> {
|
fn compute_average(values: &[Value], name: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||||
let name = name.into();
|
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(|| {
|
let number = BigDecimal::from_usize(2).ok_or_else(|| {
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"could not convert to big decimal",
|
"could not convert to big decimal",
|
||||||
|
@ -3,6 +3,7 @@ pub mod command;
|
|||||||
pub mod max;
|
pub mod max;
|
||||||
pub mod median;
|
pub mod median;
|
||||||
pub mod min;
|
pub mod min;
|
||||||
|
pub mod sum;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub use average::SubCommand as MathAverage;
|
pub use average::SubCommand as MathAverage;
|
||||||
@ -10,3 +11,4 @@ pub use command::Command as Math;
|
|||||||
pub use max::SubCommand as MathMaximum;
|
pub use max::SubCommand as MathMaximum;
|
||||||
pub use median::SubCommand as MathMedian;
|
pub use median::SubCommand as MathMedian;
|
||||||
pub use min::SubCommand as MathMinimum;
|
pub use min::SubCommand as MathMinimum;
|
||||||
|
pub use sum::SubCommand as MathSummation;
|
||||||
|
@ -1,26 +1,25 @@
|
|||||||
|
use crate::commands::math::utils::calculate;
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::utils::data_processing::{reducer_for, Reduce};
|
use crate::utils::data_processing::{reducer_for, Reduce};
|
||||||
use nu_errors::ShellError;
|
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 num_traits::identities::Zero;
|
||||||
|
|
||||||
use indexmap::map::IndexMap;
|
pub struct SubCommand;
|
||||||
|
|
||||||
pub struct Sum;
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WholeStreamCommand for Sum {
|
impl WholeStreamCommand for SubCommand {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"sum"
|
"math sum"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("sum")
|
Signature::build("math sum")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Sums the values."
|
"Finds the sum of a list of numbers or tables"
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(
|
async fn run(
|
||||||
@ -28,16 +27,19 @@ impl WholeStreamCommand for Sum {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
sum(RunnableContext {
|
calculate(
|
||||||
input: args.input,
|
RunnableContext {
|
||||||
registry: registry.clone(),
|
input: args.input,
|
||||||
shell_manager: args.shell_manager,
|
registry: registry.clone(),
|
||||||
host: args.host,
|
shell_manager: args.shell_manager,
|
||||||
ctrl_c: args.ctrl_c,
|
host: args.host,
|
||||||
current_errors: args.current_errors,
|
ctrl_c: args.ctrl_c,
|
||||||
name: args.call_info.name_tag,
|
current_errors: args.current_errors,
|
||||||
raw_input: args.raw_input,
|
name: args.call_info.name_tag,
|
||||||
})
|
raw_input: args.raw_input,
|
||||||
|
},
|
||||||
|
summation,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,31 +47,28 @@ impl WholeStreamCommand for Sum {
|
|||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
description: "Sum a list of numbers",
|
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()]),
|
result: Some(vec![UntaggedValue::int(6).into()]),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Get the disk usage for the current directory",
|
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,
|
result: None,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sum(
|
pub fn summation(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
|
||||||
RunnableContext { mut input, .. }: RunnableContext,
|
let sum = reducer_for(Reduce::Summation);
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let values: Vec<Value> = input.drain_vec().await;
|
|
||||||
let action = reducer_for(Reduce::Sum);
|
|
||||||
|
|
||||||
if values.iter().all(|v| v.is_primitive()) {
|
if values.iter().all(|v| v.is_primitive()) {
|
||||||
let total = action(Value::zero(), values)?;
|
Ok(sum(Value::zero(), values.to_vec())?)
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(total)))
|
|
||||||
} else {
|
} else {
|
||||||
let mut column_values = IndexMap::new();
|
let mut column_values = IndexMap::new();
|
||||||
|
|
||||||
for value in values {
|
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() {
|
for (key, value) in row_dict.entries.iter() {
|
||||||
column_values
|
column_values
|
||||||
.entry(key.clone())
|
.entry(key.clone())
|
||||||
@ -80,32 +79,28 @@ async fn sum(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut column_totals = IndexMap::new();
|
let mut column_totals = IndexMap::new();
|
||||||
|
|
||||||
for (col_name, col_vals) in column_values {
|
for (col_name, col_vals) in column_values {
|
||||||
let sum = action(Value::zero(), col_vals);
|
let sum = sum(Value::zero(), col_vals)?;
|
||||||
match sum {
|
|
||||||
Ok(value) => {
|
column_totals.insert(col_name, sum);
|
||||||
column_totals.insert(col_name, value);
|
|
||||||
}
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(
|
|
||||||
UntaggedValue::Row(Dictionary {
|
Ok(UntaggedValue::Row(Dictionary {
|
||||||
entries: column_totals,
|
entries: column_totals,
|
||||||
})
|
})
|
||||||
.into_untagged_value(),
|
.into_value(name))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Sum;
|
use super::SubCommand;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn examples_work_as_expected() {
|
fn examples_work_as_expected() {
|
||||||
use crate::examples::test as test_examples;
|
use crate::examples::test as test_examples;
|
||||||
|
|
||||||
test_examples(Sum {})
|
test_examples(SubCommand {})
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -288,14 +288,14 @@ pub fn reducer_for(
|
|||||||
command: Reduce,
|
command: Reduce,
|
||||||
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
|
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
|
||||||
match command {
|
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::Minimum => Box::new(|_, values| min(values)),
|
||||||
Reduce::Maximum => Box::new(|_, values| max(values)),
|
Reduce::Maximum => Box::new(|_, values| max(values)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Reduce {
|
pub enum Reduce {
|
||||||
Sum,
|
Summation,
|
||||||
Minimum,
|
Minimum,
|
||||||
Maximum,
|
Maximum,
|
||||||
Default,
|
Default,
|
||||||
@ -309,7 +309,7 @@ pub fn reduce(
|
|||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
let reduce_with = match reducer {
|
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 == "min" => reducer_for(Reduce::Minimum),
|
||||||
Some(cmd) if cmd == "max" => reducer_for(Reduce::Maximum),
|
Some(cmd) if cmd == "max" => reducer_for(Reduce::Maximum),
|
||||||
Some(_) | None => reducer_for(Reduce::Default),
|
Some(_) | None => reducer_for(Reduce::Default),
|
||||||
@ -642,7 +642,7 @@ mod tests {
|
|||||||
fn reducer_computes_given_a_sum_command() -> Result<(), ShellError> {
|
fn reducer_computes_given_a_sum_command() -> Result<(), ShellError> {
|
||||||
let subject = vec![int(1), int(1), int(1)];
|
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));
|
assert_eq!(action(Value::zero(), subject)?, int(3));
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use nu_test_support::nu;
|
|||||||
fn drop_rows() {
|
fn drop_rows() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
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");
|
assert_eq!(actual.out, "3");
|
||||||
|
@ -5,7 +5,7 @@ fn each_works_separately() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
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
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ fn adds_value_provided_if_column_is_empty() {
|
|||||||
open likes.csv
|
open likes.csv
|
||||||
| empty? likes 1
|
| empty? likes 1
|
||||||
| get likes
|
| get likes
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
@ -43,7 +43,7 @@ fn adds_value_provided_for_columns_that_are_empty() {
|
|||||||
{"boost": 1, "check": {}},
|
{"boost": 1, "check": {}},
|
||||||
{"boost": null, "check": ["" {} [] ""]}
|
{"boost": null, "check": ["" {} [] ""]}
|
||||||
]
|
]
|
||||||
|
|
||||||
"#,
|
"#,
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ fn adds_value_provided_for_columns_that_are_empty() {
|
|||||||
open checks.json
|
open checks.json
|
||||||
| empty? boost check 1
|
| empty? boost check 1
|
||||||
| get boost check
|
| get boost check
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -22,7 +22,7 @@ fn rows() {
|
|||||||
open caballeros.csv
|
open caballeros.csv
|
||||||
| keep 3
|
| keep 3
|
||||||
| get lucky_code
|
| get lucky_code
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -41,7 +41,7 @@ fn condition_is_met() {
|
|||||||
| keep-until "Chicken Collection" == "Red Chickens"
|
| keep-until "Chicken Collection" == "Red Chickens"
|
||||||
| str to-int "31/04/2020"
|
| str to-int "31/04/2020"
|
||||||
| get "31/04/2020"
|
| get "31/04/2020"
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -41,7 +41,7 @@ fn condition_is_met() {
|
|||||||
| keep-while "Chicken Collection" != "Blue Chickens"
|
| keep-while "Chicken Collection" != "Blue Chickens"
|
||||||
| str to-int "31/04/2020"
|
| str to-int "31/04/2020"
|
||||||
| get "31/04/2020"
|
| get "31/04/2020"
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -33,7 +33,7 @@ fn row() {
|
|||||||
| merge { open new_caballeros.csv }
|
| merge { open new_caballeros.csv }
|
||||||
| where country in: ["Guayaquil Ecuador" "New Zealand"]
|
| where country in: ["Guayaquil Ecuador" "New Zealand"]
|
||||||
| get luck
|
| get luck
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -40,7 +40,7 @@ fn condition_is_met() {
|
|||||||
| skip-until "Chicken Collection" == "Red Chickens"
|
| skip-until "Chicken Collection" == "Red Chickens"
|
||||||
| str to-int "31/04/2020"
|
| str to-int "31/04/2020"
|
||||||
| get "31/04/2020"
|
| get "31/04/2020"
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -108,7 +108,7 @@ fn converts_to_decimal() {
|
|||||||
echo "3.1, 0.0415"
|
echo "3.1, 0.0415"
|
||||||
| split row ","
|
| split row ","
|
||||||
| str to-decimal
|
| str to-decimal
|
||||||
| sum
|
| math sum
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ fn sets() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.toml
|
open sample.toml
|
||||||
| str set wykittenshell package.name
|
| str set wykittenshell package.name
|
||||||
| get package.name
|
| get package.name
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
|
@ -25,7 +25,7 @@ fn all() {
|
|||||||
open meals.json
|
open meals.json
|
||||||
| get meals
|
| get meals
|
||||||
| get calories
|
| get calories
|
||||||
| sum
|
| math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
@ -53,7 +53,7 @@ fn outputs_zero_with_no_input() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
sum
|
math sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
@ -74,7 +74,7 @@ fn compute_sum_of_individual_row() -> Result<(), String> {
|
|||||||
for (column_name, expected_value) in answers_for_columns.iter() {
|
for (column_name, expected_value) in answers_for_columns.iter() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats/",
|
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 =
|
let result =
|
||||||
f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?;
|
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() {
|
for (column_name, expected_value) in answers_for_columns.iter() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats/",
|
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 =
|
let result =
|
||||||
f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?;
|
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() {
|
fn sum_of_a_row_containing_a_table_is_an_error() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats/",
|
cwd: "tests/fixtures/formats/",
|
||||||
"open sample-sys-output.json | sum"
|
"open sample-sys-output.json | math sum"
|
||||||
);
|
);
|
||||||
assert!(actual
|
assert!(actual
|
||||||
.err
|
.err
|
||||||
|
@ -14,7 +14,7 @@ fn filters_by_unit_size_comparison() {
|
|||||||
fn filters_with_nothing_comparison() {
|
fn filters_with_nothing_comparison() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
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");
|
assert_eq!(actual.out, "7");
|
||||||
@ -24,7 +24,7 @@ fn filters_with_nothing_comparison() {
|
|||||||
fn where_in_table() {
|
fn where_in_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
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");
|
assert_eq!(actual.out, "5");
|
||||||
@ -34,7 +34,7 @@ fn where_in_table() {
|
|||||||
fn where_not_in_table() {
|
fn where_not_in_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
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");
|
assert_eq!(actual.out, "4");
|
||||||
|
@ -36,14 +36,14 @@ mod tests {
|
|||||||
| from-csv
|
| from-csv
|
||||||
| get rusty_luck
|
| get rusty_luck
|
||||||
| str --to-int
|
| str --to-int
|
||||||
| sum
|
| math sum
|
||||||
| echo "$it"
|
| echo "$it"
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
actual,
|
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""#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,95 +1,126 @@
|
|||||||
# math
|
# math
|
||||||
|
|
||||||
Mathematical functions that generally only operate on a list of numbers (integers, decimals, bytes) and tables.
|
Mathematical functions that generally only operate on a list of numbers (integers, decimals, bytes) and tables.
|
||||||
Currently the following functions are implemented:
|
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 average`: Finds the average of a list of numbers or tables
|
||||||
`math max` Get the maximum of a list of numbers
|
* `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`.
|
However, the mathematical functions like `min` and `max` are more permissive and also work on `Dates`.
|
||||||
|
|
||||||
## Examples
|
## 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.
|
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)
|
### List of Numbers (Integers, Decimals, Bytes)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
> ls
|
> ls
|
||||||
# │ name │ type │ size │ modified
|
# │ name │ type │ size │ modified
|
||||||
────┼────────────────────┼──────┼──────────┼─────────────
|
────┼────────────────────┼──────┼──────────┼─────────────
|
||||||
0 │ CODE_OF_CONDUCT.md │ File │ 3.4 KB │ 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
|
1 │ CONTRIBUTING.md │ File │ 1.3 KB │ 4 days ago
|
||||||
2 │ Cargo.lock │ File │ 106.3 KB │ 6 mins ago
|
2 │ Cargo.lock │ File │ 106.3 KB │ 6 mins ago
|
||||||
3 │ Cargo.toml │ File │ 4.6 KB │ 3 days ago
|
3 │ Cargo.toml │ File │ 4.6 KB │ 3 days ago
|
||||||
4 │ LICENSE │ File │ 1.1 KB │ 4 days ago
|
4 │ LICENSE │ File │ 1.1 KB │ 4 days ago
|
||||||
5 │ Makefile.toml │ File │ 449 B │ 4 days ago
|
5 │ Makefile.toml │ File │ 449 B │ 4 days ago
|
||||||
6 │ README.md │ File │ 16.0 KB │ 6 mins ago
|
6 │ README.md │ File │ 16.0 KB │ 6 mins ago
|
||||||
7 │ TODO.md │ File │ 0 B │ 6 mins ago
|
7 │ TODO.md │ File │ 0 B │ 6 mins ago
|
||||||
8 │ assets │ Dir │ 128 B │ 4 days ago
|
8 │ assets │ Dir │ 128 B │ 4 days ago
|
||||||
9 │ build.rs │ File │ 78 B │ 4 days ago
|
9 │ build.rs │ File │ 78 B │ 4 days ago
|
||||||
10 │ crates │ Dir │ 672 B │ 3 days ago
|
10 │ crates │ Dir │ 672 B │ 3 days ago
|
||||||
11 │ debian │ Dir │ 352 B │ 4 days ago
|
11 │ debian │ Dir │ 352 B │ 4 days ago
|
||||||
12 │ docker │ Dir │ 288 B │ 4 days ago
|
12 │ docker │ Dir │ 288 B │ 4 days ago
|
||||||
13 │ docs │ Dir │ 160 B │ 4 days ago
|
13 │ docs │ Dir │ 160 B │ 4 days ago
|
||||||
14 │ features.toml │ File │ 632 B │ 4 days ago
|
14 │ features.toml │ File │ 632 B │ 4 days ago
|
||||||
15 │ images │ Dir │ 160 B │ 4 days ago
|
15 │ images │ Dir │ 160 B │ 4 days ago
|
||||||
16 │ justfile │ File │ 234 B │ 3 days ago
|
16 │ justfile │ File │ 234 B │ 3 days ago
|
||||||
17 │ rustfmt.toml │ File │ 16 B │ 4 days ago
|
17 │ rustfmt.toml │ File │ 16 B │ 4 days ago
|
||||||
18 │ src │ Dir │ 128 B │ 4 days ago
|
18 │ src │ Dir │ 128 B │ 4 days ago
|
||||||
19 │ target │ Dir │ 192 B │ 8 hours ago
|
19 │ target │ Dir │ 192 B │ 8 hours ago
|
||||||
20 │ tests │ Dir │ 192 B │ 4 days ago
|
20 │ tests │ Dir │ 192 B │ 4 days ago
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
> ls | get size | math average
|
> ls | get size | math average
|
||||||
───┬────────
|
───┬────────
|
||||||
0 │ 6.5 KB
|
0 │ 7.2 KB
|
||||||
───┴────────
|
───┴────────
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
> ls | get size | math min
|
> ls | get size | math min
|
||||||
───┬─────
|
───┬─────
|
||||||
0 │ 0 B
|
0 │ 0 B
|
||||||
───┴─────
|
───┴─────
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
> ls | get size | math max
|
> 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
|
> ls | get modified | math min
|
||||||
2020-06-09 17:25:51.798743222 UTC
|
2020-06-09 17:25:51.798743222 UTC
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
> ls | get modified | math max
|
> ls | get modified | math max
|
||||||
2020-06-14 05:49:59.637449186 UT
|
2020-06-14 05:49:59.637449186 UT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Operations on tables
|
### 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
|
> pwd | split row / | size | math max
|
||||||
───────────┬───
|
───────────┬───
|
||||||
lines │ 0
|
lines │ 0
|
||||||
words │ 1
|
words │ 1
|
||||||
chars │ 9
|
chars │ 9
|
||||||
max length │ 9
|
max length │ 9
|
||||||
────────────┴───
|
────────────┴───
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
> pwd | split row / | size | math average
|
> pwd | split row / | size | math average
|
||||||
────────────┬────────
|
────────────┬────────
|
||||||
lines │ 0.0000
|
lines │ 0.0000
|
||||||
words │ 1.0000
|
words │ 1.0000
|
||||||
chars │ 7.0000
|
chars │ 7.0000
|
||||||
max length │ 7.0000
|
max length │ 7.0000
|
||||||
────────────┴────────
|
────────────┴────────
|
||||||
```
|
```
|
||||||
|
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
`math` functions are aggregation functions so empty lists are invalid
|
`math` functions are aggregation functions so empty lists are invalid
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
> echo [] | math average
|
> echo [] | math average
|
||||||
error: Error: Unexpected: Cannot perform aggregate math operation on empty data
|
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
|
> echo [1 2 a ] | math average
|
||||||
0
|
0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ Applies the subcommand to a value or a table.
|
|||||||
1 │ │ filesystem │
|
1 │ │ filesystem │
|
||||||
━━━┷━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━┷━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
> echo "1, 2, 3" | split row "," | str to-int | sum
|
> echo "1, 2, 3" | split row "," | str to-int | math sum
|
||||||
━━━━━━━━━
|
━━━━━━━━━
|
||||||
<value>
|
<value>
|
||||||
─────────
|
─────────
|
||||||
|
@ -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.
|
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
|
```shell
|
||||||
> ls | get size | sum
|
> ls | get size | math sum
|
||||||
━━━━━━━━━
|
━━━━━━━━━
|
||||||
value
|
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.
|
To get the sum of the characters that make up your present working directory.
|
||||||
```shell
|
```shell
|
||||||
> pwd | split-row / | size | get chars | sum
|
> pwd | split-row / | size | get chars | math sum
|
||||||
━━━━━━━━━
|
━━━━━━━━━
|
||||||
<value>
|
<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`
|
One way to solve this is to convert each row to an integer when possible and then pipe the result to `sum`
|
||||||
|
|
||||||
```shell
|
```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"))
|
error: Unrecognized type in stream: Primitive(String("2509000000"))
|
||||||
- shell:1:0
|
- 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
|
| ^^^^ source
|
||||||
```
|
```
|
||||||
|
|
||||||
```shell
|
```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>
|
<value>
|
||||||
─────────────
|
─────────────
|
||||||
|
@ -198,7 +198,7 @@ fn echoing_ranges() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".",
|
cwd: ".",
|
||||||
r#"
|
r#"
|
||||||
echo 1..3 | sum
|
echo 1..3 | math sum
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user