Skip to content

Add array_combinations_with_replacement #1033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

mendelsshop
Copy link

@mendelsshop mendelsshop commented Jun 13, 2025

This PR adds a new method for iterators called array_combinations_with_replacement which is similar to combinations_with_replacement, except for that it uses const generics and arrays.

This is similar to array_combinations and combinations.
I also generalized the underlying CombinationsWithReplacement type similar to how it is done with Combinations.

This closes #1025.

Copy link

codecov bot commented Jun 13, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.24%. Comparing base (6814180) to head (189c15e).
Report is 141 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1033      +/-   ##
==========================================
- Coverage   94.38%   94.24%   -0.14%     
==========================================
  Files          48       50       +2     
  Lines        6665     6226     -439     
==========================================
- Hits         6291     5868     -423     
+ Misses        374      358      -16     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@phimuemue phimuemue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi there, thanks a lot for this.

Looks very good to me. Could you address my questions and add some tests?

And I think Box is only available with under #[cfg(feature = "use_alloc")].


fn next(&mut self) -> Option<Self::Item> {
if self.first {
// In empty edge cases, stop iterating immediately
if !(self.indices.is_empty() || self.pool.get_next()) {
if !(core::borrow::Borrow::<[usize]>::borrow(&self.indices).is_empty()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we write self.indices.borrow()?

Copy link
Author

@mendelsshop mendelsshop Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird, that work, when I originally tried doing that I got an error, but now it works.

@@ -24,6 +24,10 @@ where

/// Iterator for `Box<[I]>` valued combinations_with_replacement returned by [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement)
pub type CombinationsWithReplacement<I> = CombinationsWithReplacementGeneric<I, Box<[usize]>>;
/// Iterator for const generic combinations_with_replacement returned by [`.array_combinations_with_replacement()`](crate::Itertools::array_combinations_with_replacement)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-markdown expert here: Is the (crate::Itertools::array_combinations_with_replacement) required?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know I just copied and modified the doc comment from two lines above.

@mendelsshop
Copy link
Author

mendelsshop commented Jun 13, 2025

And I think Box is only available with under #[cfg(feature = "use_alloc")].

The whole combinations_with_replacement file seems to feature gated under #[cfg(feature = "use_alloc")].

Edit:
I did not see CI failed, I just pushed something.

@mendelsshop
Copy link
Author

I added test for array_combinations_with_replacement mostly based on the test already there for combinations_with_replacement except when I could not because they could not be done in const context easily.

@mendelsshop mendelsshop requested a review from phimuemue June 13, 2025 16:19
Copy link
Member

@phimuemue phimuemue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. Could you fix so that CI runs through?

Can you limit the cfgs to where they are necessary please?

And by the way: Thanks for splitting up the PR into nicely diffable chunks, and for just amending instead of force-pushing and overwriting old commits.

@@ -52,7 +52,16 @@ pub trait PoolIndex<T>: BorrowMut<[usize]> {
self.borrow().len()
}
}
impl<T> PoolIndex<T> for Box<[usize]> {
type Item = Vec<T>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can think about returning Box<[T]> later, but since we'd probably construct it via a Vec, Vec is fine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just what did not change that, as that was the way it was before.

@@ -1,3 +1,4 @@
#[cfg(feature = "use_alloc")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think cfg(feature="use_alloc") in combinations_with_replacement.rs is redundant because the module itself is only conditionally (see https://github.com/rust-itertools/itertools/blob/master/src/lib.rs#L101-L102). Please double-check and remove them if that's the case.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I see, I was getting confused because of a missing Box import, when writing it.

@mendelsshop
Copy link
Author

Maybe we should remove the cfg(feature="use_alloc") from the module itself, as I don't think (but I could be wrong) that the array or generic versions need alloc. The same thing could also be done for regular combinations too.

`combinations_with_replacements` as they are done at a module level
right now.
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.

Feature request: array_combinations_with_replacement
2 participants