Repository: rust-itertools/itertools (language: rust)

Issue:
`k_smallest[_by]/tail`: similarities and differences
I find my new `tail` (#899) quite similar to `k_smallest` and its recent variants: we fuse the iterator, collect a limited number of items, than update the resulting slice with `iter.for_each`.

In `tail`, I consume the iterator (doing so can have wanted side effects) even when `n = 0` while `k_smallest` and variants do not but merely drop it.
In `tail`, I have a special case for `n = 1` while `k_smallest` and variants do not (it could use a possibly faster `min[_by]`).

I think we should update `k_smallest` and `k_smallest_general` accordingly.

Do you see other differences we should fix?


Discussion / hints:

Fix patch:
diff --git a/src/k_smallest.rs b/src/k_smallest.rs
index b909887f5..7b2f62ea1 100644
--- a/src/k_smallest.rs
+++ b/src/k_smallest.rs
@@ -42,8 +42,12 @@ where
     }
 
     if k == 0 {
+        iter.last();
         return Vec::new();
     }
+    if k == 1 {
+        return iter.min_by(comparator).into_iter().collect();
+    }
     let mut iter = iter.fuse();
     let mut storage: Vec<I::Item> = iter.by_ref().take(k).collect();
 
diff --git a/src/lib.rs b/src/lib.rs
index a297a6d80..ff14cf94e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2972,8 +2972,12 @@ pub trait Itertools: Iterator {
         use alloc::collections::BinaryHeap;
 
         if k == 0 {
+            self.last();
             return Vec::new().into_iter();
         }
+        if k == 1 {
+            return self.min().into_iter().collect_vec().into_iter();
+        }
 
         let mut iter = self.fuse();
         let mut heap: BinaryHeap<_> = iter.by_ref().take(k).collect();


Test patch: