mirror of
https://github.com/nushell/nushell.git
synced 2025-04-09 21:28:55 +02:00
window --remainder (#6738)
* Implement window remainder, and save allocation * Fallible memory reservation
This commit is contained in:
parent
4ffa4ac42a
commit
e22f2e9f13
@ -23,6 +23,11 @@ impl Command for Window {
|
|||||||
"the number of rows to slide over between windows",
|
"the number of rows to slide over between windows",
|
||||||
Some('s'),
|
Some('s'),
|
||||||
)
|
)
|
||||||
|
.switch(
|
||||||
|
"remainder",
|
||||||
|
"yield last chunks even if they have fewer elements than size",
|
||||||
|
Some('r'),
|
||||||
|
)
|
||||||
.category(Category::Filters)
|
.category(Category::Filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +120,39 @@ impl Command for Window {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let stream_test_3 = vec![
|
||||||
|
Value::List {
|
||||||
|
vals: vec![
|
||||||
|
Value::Int {
|
||||||
|
val: 1,
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: 2,
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: 3,
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
Value::List {
|
||||||
|
vals: vec![
|
||||||
|
Value::Int {
|
||||||
|
val: 4,
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: 5,
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: Span::test_data(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
example: "echo [1 2 3 4] | window 2",
|
example: "echo [1 2 3 4] | window 2",
|
||||||
@ -132,6 +170,14 @@ impl Command for Window {
|
|||||||
span: Span::test_data(),
|
span: Span::test_data(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
example: "[1, 2, 3, 4, 5] | window 3 --stride 3 --remainder",
|
||||||
|
description: "A sliding window of equal stride that includes remainder. Equivalent to chunking",
|
||||||
|
result: Some(Value::List {
|
||||||
|
vals: stream_test_3,
|
||||||
|
span: Span::test_data(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +192,7 @@ impl Command for Window {
|
|||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
let stride: Option<usize> = call.get_flag(engine_state, stack, "stride")?;
|
let stride: Option<usize> = call.get_flag(engine_state, stack, "stride")?;
|
||||||
|
let remainder = call.has_flag("remainder");
|
||||||
|
|
||||||
let stride = stride.unwrap_or(1);
|
let stride = stride.unwrap_or(1);
|
||||||
|
|
||||||
@ -157,6 +204,7 @@ impl Command for Window {
|
|||||||
span: call.head,
|
span: call.head,
|
||||||
previous: None,
|
previous: None,
|
||||||
stride,
|
stride,
|
||||||
|
remainder,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(each_group_iterator
|
Ok(each_group_iterator
|
||||||
@ -171,13 +219,21 @@ struct EachWindowIterator {
|
|||||||
span: Span,
|
span: Span,
|
||||||
previous: Option<Vec<Value>>,
|
previous: Option<Vec<Value>>,
|
||||||
stride: usize,
|
stride: usize,
|
||||||
|
remainder: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for EachWindowIterator {
|
impl Iterator for EachWindowIterator {
|
||||||
type Item = Value;
|
type Item = Value;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let mut group = self.previous.take().unwrap_or_default();
|
let mut group = self.previous.take().unwrap_or_else(|| {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
// We default to a Vec of capacity size + stride as striding pushes n extra elements to the end
|
||||||
|
vec.try_reserve(self.group_size + self.stride).ok();
|
||||||
|
|
||||||
|
vec
|
||||||
|
});
|
||||||
let mut current_count = 0;
|
let mut current_count = 0;
|
||||||
|
|
||||||
if group.is_empty() {
|
if group.is_empty() {
|
||||||
@ -193,7 +249,13 @@ impl Iterator for EachWindowIterator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => return None,
|
None => {
|
||||||
|
if self.remainder {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -211,14 +273,23 @@ impl Iterator for EachWindowIterator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => return None,
|
None => {
|
||||||
|
if self.remainder {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group = group[current_count..].to_vec();
|
// We now have elements + stride in our group, and need to
|
||||||
|
// drop the skipped elements. Drain to preserve allocation and capacity
|
||||||
|
// Dropping this iterator consumes it.
|
||||||
|
group.drain(..self.stride.min(group.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.is_empty() || current_count == 0 {
|
if group.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user