mirror of
https://github.com/nushell/nushell.git
synced 2025-04-25 05:38:20 +02:00
uniq
code refactoring (#7188)
# Description While trying to add a new `uniq-by` command I refactored the `uniq` command code to understand it and try to reuse. I think this is more compact and easier to understand. The part that I think it's a little confusing in this refactor is the conditions inside `.filters()`, for example: `!flag_show_repeated || (value.1 > 1)`. I could use `if (flag_show_repeated) {value.1 > 1} else {true}` but it is more verbose, what do you think? PS: Not sure if you like this kind of PR, sorry if not. # Tests + Formatting I also added a test where the `uniq` has a table as input.
This commit is contained in:
parent
b12ffb8888
commit
f46c45343a
@ -1,5 +1,3 @@
|
|||||||
use std::collections::VecDeque;
|
|
||||||
|
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
@ -135,6 +133,23 @@ fn to_lowercase(value: nu_protocol::Value) -> nu_protocol::Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_results_with_count(head: Span, uniq_values: Vec<(Value, i64)>) -> Vec<Value> {
|
||||||
|
uniq_values
|
||||||
|
.into_iter()
|
||||||
|
.map(|item| Value::Record {
|
||||||
|
cols: vec!["value".to_string(), "count".to_string()],
|
||||||
|
vals: vec![
|
||||||
|
item.0,
|
||||||
|
Value::Int {
|
||||||
|
val: item.1,
|
||||||
|
span: head,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: head,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn uniq(
|
fn uniq(
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
@ -142,73 +157,45 @@ fn uniq(
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
let should_show_count = call.has_flag("count");
|
let flag_show_count = call.has_flag("count");
|
||||||
let show_repeated = call.has_flag("repeated");
|
let flag_show_repeated = call.has_flag("repeated");
|
||||||
let ignore_case = call.has_flag("ignore-case");
|
let flag_ignore_case = call.has_flag("ignore-case");
|
||||||
let only_uniques = call.has_flag("unique");
|
let flag_only_uniques = call.has_flag("unique");
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
|
||||||
let uniq_values = {
|
let mut uniq_values = input
|
||||||
let counter = &mut Vec::new();
|
.into_iter()
|
||||||
for line in input.into_iter() {
|
.map(|item| {
|
||||||
let item = if ignore_case {
|
if flag_ignore_case {
|
||||||
to_lowercase(line)
|
to_lowercase(item)
|
||||||
} else {
|
} else {
|
||||||
line
|
item
|
||||||
};
|
}
|
||||||
|
})
|
||||||
if counter.is_empty() {
|
.fold(Vec::<(Value, i64)>::new(), |mut counter, item| {
|
||||||
counter.push((item, 1));
|
|
||||||
} else {
|
|
||||||
// check if the value item already exists in our collection. if it does, increase counter, otherwise add it to the collection
|
|
||||||
match counter.iter_mut().find(|x| x.0 == item) {
|
match counter.iter_mut().find(|x| x.0 == item) {
|
||||||
Some(x) => x.1 += 1,
|
Some(x) => x.1 += 1,
|
||||||
None => counter.push((item, 1)),
|
None => counter.push((item, 1)),
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
counter.to_vec()
|
|
||||||
};
|
};
|
||||||
|
counter
|
||||||
let uv = uniq_values.to_vec();
|
|
||||||
let mut values = if show_repeated {
|
|
||||||
uv.into_iter().filter(|i| i.1 > 1).collect()
|
|
||||||
} else {
|
|
||||||
uv
|
|
||||||
};
|
|
||||||
|
|
||||||
if only_uniques {
|
|
||||||
values = values.into_iter().filter(|i| i.1 == 1).collect::<_>()
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut values_vec_deque = VecDeque::new();
|
|
||||||
|
|
||||||
if should_show_count {
|
|
||||||
for item in values {
|
|
||||||
values_vec_deque.push_back({
|
|
||||||
let cols = vec!["value".to_string(), "count".to_string()];
|
|
||||||
let vals = vec![
|
|
||||||
item.0,
|
|
||||||
Value::Int {
|
|
||||||
val: item.1,
|
|
||||||
span: head,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
Value::Record {
|
|
||||||
cols,
|
|
||||||
vals,
|
|
||||||
span: head,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if flag_show_repeated {
|
||||||
|
uniq_values.retain(|value_count_pair| value_count_pair.1 > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flag_only_uniques {
|
||||||
|
uniq_values.retain(|value_count_pair| value_count_pair.1 == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = if flag_show_count {
|
||||||
|
generate_results_with_count(head, uniq_values)
|
||||||
} else {
|
} else {
|
||||||
for item in values {
|
uniq_values.into_iter().map(|v| v.0).collect()
|
||||||
values_vec_deque.push_back(item.0);
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::List {
|
Ok(Value::List {
|
||||||
vals: values_vec_deque.into_iter().collect(),
|
vals: result,
|
||||||
span: head,
|
span: head,
|
||||||
}
|
}
|
||||||
.into_pipeline_data()
|
.into_pipeline_data()
|
||||||
|
@ -230,3 +230,24 @@ fn uniq_simple_vals_strs() {
|
|||||||
print!("{}", expected.out);
|
print!("{}", expected.out);
|
||||||
assert_eq!(actual.out, expected.out);
|
assert_eq!(actual.out, expected.out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_table() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
|
r#"
|
||||||
|
[[fruit day]; [apple monday] [apple friday] [apple monday] [pear monday] [orange tuesday]]
|
||||||
|
| uniq
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
let expected = nu!(
|
||||||
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
|
r#"
|
||||||
|
echo [[fruit day]; [apple monday] [apple friday] [pear monday] [orange tuesday]]
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
print!("{}", actual.out);
|
||||||
|
print!("{}", expected.out);
|
||||||
|
assert_eq!(actual.out, expected.out);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user