diff --git a/crates/nu-command/src/filters/select.rs b/crates/nu-command/src/filters/select.rs index 3be756729..b1a627487 100644 --- a/crates/nu-command/src/filters/select.rs +++ b/crates/nu-command/src/filters/select.rs @@ -5,6 +5,7 @@ use nu_protocol::{ Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, PipelineIterator, ShellError, Signature, Span, SyntaxShape, Type, Value, }; +use std::collections::HashSet; #[derive(Clone)] pub struct Select; @@ -98,7 +99,7 @@ fn select( input: PipelineData, ignore_errors: bool, ) -> Result { - let mut rows = vec![]; + let mut unique_rows: HashSet = HashSet::new(); let mut new_columns = vec![]; @@ -118,23 +119,32 @@ fn select( Vec::new(), )); } - - rows.push(*val); + if unique_rows.contains(val) { + return Err(ShellError::GenericError( + "Select can't get the same row twice".into(), + "duplicated row index".into(), + Some(*span), + None, + Vec::new(), + )); + } + unique_rows.insert(*val); } _ => new_columns.push(column), }; } let columns = new_columns; + let mut unique_rows: Vec = unique_rows.into_iter().collect(); - let input = if !rows.is_empty() { - rows.sort_unstable(); + let input = if !unique_rows.is_empty() { + unique_rows.sort_unstable(); // let skip = call.has_flag("skip"); let metadata = input.metadata(); let pipeline_iter: PipelineIterator = input.into_iter(); NthIterator { input: pipeline_iter, - rows, + rows: unique_rows, skip: false, current: 0, } diff --git a/crates/nu-command/tests/commands/select.rs b/crates/nu-command/tests/commands/select.rs index f13751c8e..e01eb2a0a 100644 --- a/crates/nu-command/tests/commands/select.rs +++ b/crates/nu-command/tests/commands/select.rs @@ -272,3 +272,15 @@ fn select_failed3() { assert!(actual.out.is_empty()); assert!(actual.err.contains("cannot find column")); } + +#[test] +fn select_failed4() { + let actual = nu!( + cwd: ".", pipeline( + r#" + [{a: 1 b: 10}, {a:2, b:11}] | select 0 0 + "# + )); + + assert!(actual.err.contains("Select can't get the same row twice")); +}