mirror of
https://github.com/nushell/nushell
synced 2024-12-26 04:53:09 +00:00
reject
multiple row args support (#10163)
# Description This PR fixes `reject` failing when providing row items in ascending order. # User-Facing Changes users can now `reject` multiple rows independently of each other. ```nushell let foo = [[a b]; [ 1 2] [3 4] [ 5 6]] # this will work independant of the order print ($foo | reject 2 1) print ($foo | reject 1 2) ``` --------- Co-authored-by: Antoine Stevan <44101798+amtoine@users.noreply.github.com>
This commit is contained in:
parent
17abbdf6e0
commit
248aca7a44
2 changed files with 70 additions and 7 deletions
|
@ -1,10 +1,12 @@
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::ast::{Call, CellPath};
|
use nu_protocol::ast::{Call, CellPath, PathMember};
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span,
|
Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span,
|
||||||
SyntaxShape, Type, Value,
|
SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
|
use std::cmp::Reverse;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Reject;
|
pub struct Reject;
|
||||||
|
@ -70,6 +72,17 @@ impl Command for Reject {
|
||||||
Span::test_data(),
|
Span::test_data(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
description: "Reject a row in a table",
|
||||||
|
example: "[[a, b]; [1, 2] [3, 4]] | reject 1",
|
||||||
|
result: Some(Value::List {
|
||||||
|
vals: vec![Value::test_record(Record {
|
||||||
|
cols: vec!["a".to_string(), "b".to_string()],
|
||||||
|
vals: vec![Value::test_int(1), Value::test_int(2)],
|
||||||
|
})],
|
||||||
|
span: Span::test_data(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Reject the specified field in a record",
|
description: "Reject the specified field in a record",
|
||||||
example: "{a: 1, b: 2} | reject a",
|
example: "{a: 1, b: 2} | reject a",
|
||||||
|
@ -99,15 +112,47 @@ fn reject(
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
cell_paths: Vec<CellPath>,
|
cell_paths: Vec<CellPath>,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let mut unique_rows: HashSet<usize> = HashSet::new();
|
||||||
let val = input.into_value(span);
|
let val = input.into_value(span);
|
||||||
let mut val = val;
|
let mut val = val;
|
||||||
let mut columns = vec![];
|
let mut new_columns = vec![];
|
||||||
for c in cell_paths {
|
let mut new_rows = vec![];
|
||||||
if !columns.contains(&c) {
|
for column in cell_paths {
|
||||||
columns.push(c);
|
let CellPath { ref members } = column;
|
||||||
|
match members.get(0) {
|
||||||
|
Some(PathMember::Int { val, span, .. }) => {
|
||||||
|
if members.len() > 1 {
|
||||||
|
return Err(ShellError::GenericError(
|
||||||
|
"Reject only allows row numbers for rows".into(),
|
||||||
|
"extra after row number".into(),
|
||||||
|
Some(*span),
|
||||||
|
None,
|
||||||
|
Vec::new(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !unique_rows.contains(val) {
|
||||||
|
unique_rows.insert(*val);
|
||||||
|
new_rows.push(column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for cell_path in columns {
|
_ => {
|
||||||
|
if !new_columns.contains(&column) {
|
||||||
|
new_columns.push(column)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
new_rows.sort_unstable_by_key(|k| {
|
||||||
|
Reverse({
|
||||||
|
match k.members[0] {
|
||||||
|
PathMember::Int { val, .. } => val,
|
||||||
|
PathMember::String { .. } => usize::MIN,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
new_columns.append(&mut new_rows);
|
||||||
|
for cell_path in new_columns {
|
||||||
val.remove_data_at_cell_path(&cell_path.members)?;
|
val.remove_data_at_cell_path(&cell_path.members)?;
|
||||||
}
|
}
|
||||||
Ok(val.into_pipeline_data())
|
Ok(val.into_pipeline_data())
|
||||||
|
|
|
@ -79,6 +79,12 @@ fn ignores_duplicate_columns_rejected() {
|
||||||
assert_eq!(actual.out, "last name");
|
assert_eq!(actual.out, "last name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ignores_duplicate_rows_rejected() {
|
||||||
|
let actual = nu!("[[a,b];[1 2] [3 4] [5 6]] | reject 2 2 | to nuon");
|
||||||
|
assert_eq!(actual.out, "[[a, b]; [1, 2], [3, 4]]");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_record_from_raw_eval() {
|
fn reject_record_from_raw_eval() {
|
||||||
let actual = nu!(r#"{"a": 3} | reject a | describe"#);
|
let actual = nu!(r#"{"a": 3} | reject a | describe"#);
|
||||||
|
@ -143,3 +149,15 @@ fn reject_optional_row() {
|
||||||
let actual = nu!("[{foo: 'bar'}] | reject 3? | to nuon");
|
let actual = nu!("[{foo: 'bar'}] | reject 3? | to nuon");
|
||||||
assert_eq!(actual.out, "[[foo]; [bar]]");
|
assert_eq!(actual.out, "[[foo]; [bar]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reject_multiple_rows_ascending() {
|
||||||
|
let actual = nu!("[[a,b];[1 2] [3 4] [5 6]] | reject 1 2 | to nuon");
|
||||||
|
assert_eq!(actual.out, "[[a, b]; [1, 2]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reject_multiple_rows_descending() {
|
||||||
|
let actual = nu!("[[a,b];[1 2] [3 4] [5 6]] | reject 2 1 | to nuon");
|
||||||
|
assert_eq!(actual.out, "[[a, b]; [1, 2]]");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue