Skip to content

Conversation

A4-Tacks
Copy link

Collect all iterator elements into one of two partitions.
Unlike [Iterator::partition], when predicate returns true for the first time,
it collects this element and all rest elements into B.

use itertools::Itertools;

let nums = vec![0, 1, 2, 3, 4, 5];

let (a, b): (Vec<_>, Vec<_>) = nums.into_iter().split(|n| *n == 3);

assert_eq!(a, [0, 1, 2]);
assert_eq!(b, [3, 4, 5]);

Collect all iterator elements into one of two partitions.
Unlike [Itertools::split], when predicate returns true, the element is collected into A

use itertools::Itertools;

let nums = vec![0, 1, 2, 3, 4, 5];

let (a, b): (Vec<_>, Vec<_>) = nums.into_iter().split_inclusive(|n| *n == 3);

assert_eq!(a, [0, 1, 2, 3]);
assert_eq!(b, [4, 5]);

Collect all iterator elements into one of two partitions.
Unlike [`Iterator::partition`], when predicate returns true for the first time,
it collects this element and all rest elements into B.

```rust
use itertools::Itertools;

let nums = vec![0, 1, 2, 3, 4, 5];

let (a, b): (Vec<_>, Vec<_>) = nums.into_iter().split(|n| *n == 3);

assert_eq!(a, [0, 1, 2]);
assert_eq!(b, [3, 4, 5]);
```

---

Collect all iterator elements into one of two partitions.
Unlike [`Itertools::split`], when predicate returns true, the element is collected into A

```rust
use itertools::Itertools;

let nums = vec![0, 1, 2, 3, 4, 5];

let (a, b): (Vec<_>, Vec<_>) = nums.into_iter().split_inclusive(|n| *n == 3);

assert_eq!(a, [0, 1, 2, 3]);
assert_eq!(b, [4, 5]);
```
@phimuemue
Copy link
Member

Hi there. Honestly, I doubt this is really required from an API prospective, because afaik it can be expressed in terms of partition: the predicate can capture an outer bool that is flipped at the "partition point" and be returned. This "trick" might be a bit less efficient but has the advantage that it uses known functions (as opposed to the new split) - and, as a corollary, avoids the question what split should do on the second true (flip to the other container again, or ignore it).

Thus, I suggest to close this.

@phimuemue
Copy link
Member

Closing this. It can straightforwardly be implemented in terms of partition:

    { // split
        let nums = vec![0, 1, 2, 3, 4, 5];
    
        let mut put_into_first_container = true;
        let (a, b): (Vec<_>, Vec<_>) = nums.into_iter().partition(|n| {
            put_into_first_container &= *n == 3;
            put_into_first_container
        });
        
        assert_eq!(a, [0, 1, 2]);
        assert_eq!(b, [3, 4, 5]);    
    }
    
    { // split_inclusive
        let nums = vec![0, 1, 2, 3, 4, 5];

        let mut put_into_first_container = true;
        let (a, b): (Vec<_>, Vec<_>) = nums.into_iter().partition(|n| {
            let put_into_first_container_before = put_into_first_container;
            put_into_first_container &= *n == 3;
            put_into_first_container_before
        });
        
        assert_eq!(a, [0, 1, 2, 3]);
        assert_eq!(b, [4, 5]);    
    }

@phimuemue phimuemue closed this Sep 22, 2025
@A4-Tacks
Copy link
Author

The implementation of split uses extend, so that B can obtain a good size_hint to reduce allocation

@phimuemue
Copy link
Member

The implementation of split uses extend, so that B can obtain a good size_hint to reduce allocation

True, but at the cost that "swithing to the other container" is possible at most once. This begs the question "what does split do when it encounters true a second time"?

On top, it still does the extend(once(...)) for A, and if maximum performance is needed, then possibly neither partition nor split is your best bet, so I argue that users should either go with the simple partition that can emulate your split, or - if performance is needed - use a bespoke solution.

@A4-Tacks
Copy link
Author

Okay, although the split method can make things easier, it still lacks necessity

Using external flags to mark split points is really cumbersome and semantically ambiguous ...

@A4-Tacks
Copy link
Author

Closing this. It can straightforwardly be implemented in terms of partition

If the judgment conditions are complex, it is necessary to replace x &= ... with x = x && ...,
otherwise there will be additional costs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants