Skip to content
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

Extending itertools.combinations #49298

Closed
konryd mannequin opened this issue Jan 25, 2009 · 15 comments
Closed

Extending itertools.combinations #49298

konryd mannequin opened this issue Jan 25, 2009 · 15 comments
Assignees
Labels
extension-modules C modules in the Modules dir type-feature A feature request or enhancement

Comments

@konryd
Copy link
Mannequin

konryd mannequin commented Jan 25, 2009

BPO 5048
Nosy @rhettinger, @mdickinson, @ezio-melotti

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = 'https://github.com/rhettinger'
closed_at = <Date 2009-01-25.19:47:54.830>
created_at = <Date 2009-01-25.02:05:02.965>
labels = ['extension-modules', 'type-feature']
title = 'Extending itertools.combinations'
updated_at = <Date 2009-01-27.18:08:14.930>
user = 'https://bugs.python.org/konryd'

bugs.python.org fields:

activity = <Date 2009-01-27.18:08:14.930>
actor = 'rhettinger'
assignee = 'rhettinger'
closed = True
closed_date = <Date 2009-01-25.19:47:54.830>
closer = 'rhettinger'
components = ['Extension Modules']
creation = <Date 2009-01-25.02:05:02.965>
creator = 'konryd'
dependencies = []
files = []
hgrepos = []
issue_num = 5048
keywords = []
message_count = 15.0
messages = ['80492', '80495', '80498', '80499', '80500', '80501', '80506', '80532', '80533', '80536', '80617', '80645', '80646', '80648', '80664']
nosy_count = 4.0
nosy_names = ['rhettinger', 'mark.dickinson', 'ezio.melotti', 'konryd']
pr_nums = []
priority = 'normal'
resolution = 'rejected'
stage = None
status = 'closed'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue5048'
versions = ['Python 3.1', 'Python 2.7']

@konryd
Copy link
Mannequin Author

konryd mannequin commented Jan 25, 2009

The function itertools.combinations might benefit from making
the 'r' (length of the combinations) argument optionally a sequence.

With that change one could call combinations(sequence, [2, 3]) in
order to get all combinations of length 2 and 3.
In particular, one could call combinations(sequence,
range(len(sequence)) in order to get *all* combinations of given
sequence.

The change would be backwards compatible as it would check for
sequential arguments.

@konryd konryd mannequin added stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Jan 25, 2009
@rhettinger
Copy link
Contributor

Do you have compelling use cases?

Is it worth what it takes to preserve the relation with permuations()
and product() and the lexicographic orderings?

Do we care the length of the output is no longer predictable by a simple
n! / r! / (n-r)! ?

Do we care that the variable length output prevents uses in for-loops
with tuple unpacking:

   for a, b, c in combinations('ABCDEF', [2,3]):
        . . .

@rhettinger rhettinger added extension-modules C modules in the Modules dir and removed stdlib Python modules in the Lib dir labels Jan 25, 2009
@rhettinger rhettinger self-assigned this Jan 25, 2009
@ezio-melotti
Copy link
Member

It would also be nice to have a __len__ method on both permutations and
combinations.

len(permutations(sequence)) could return the number of permutations
using the formulas (e.g. n! for permutations) without generating all the
possible permutations (as opposed to something like
len(list(permutations(sequence)))).

Also, is there a way to calculate combinations with repetitions1?
Maybe we could add an optional argument repetitions=True/False.

@rhettinger
Copy link
Contributor

Guido disallowed returning a len method on iterators. He expected
bool(it) to be False.

The recipes section of the itertools docs has code for
combinations_with_replacement(). It was not included originally because
it was unclear whether there was actually a need to generate them.
Possibly, people are mainly interested in knowing how many there are but
having no need to actually enumerate them. That being said, if I get
more requests or if some real world use cases arise, I would be happy to
C the recipe and add it in Py2.7.

@mdickinson
Copy link
Member

I've seen requests for combinations with replacement come up on c.l.p. a
few times in the past, though it's never been clear whether there was a
real need or whether the interest was driven by homework or curiosity.

-1 for sequences in the second argument of combinations(); it doesn't
feel like a useful enough generalization to be worth adding code for.

@konryd
Copy link
Mannequin Author

konryd mannequin commented Jan 25, 2009

I'm afraid I don't have any real-world use cases. Originally, I assumed
that dropping the length argument will make the function iterate over
*all* combinations, which would enable me to write somehow twisted, one-
liner for _inefficiently_ solving knapsack problem.

max((comb for comb in all_combinations(zip(weights, values))
       if sum(map(itemgetter(0), comb)) < LIM), 
     key=lambda comb: sum(map(itemgetter(1), comb)))

But unfortunately, this is far from being 'compelling'.

Regarding other issues you raised: I think it would be pretty clear for
the user, that the length of every combination might vary - that's what
he asked for. And the length might be computed by summing the lengths
counted using given formula, which is (for me at last) still explicit
enough.

@mdickinson
Copy link
Member

that dropping the length argument will make the function iterate over
*all* combinations,

Now *this* sounds more useful to me: an itertool that generates *all* subsets of a list. It's
quite easy to do with existing itertools, though, either by looping over the second argument to
combinations, or (for a different ordering) using product:

def subsets(iterable):
    l = list(iterable)
    for selector in itertools.product([False, True], repeat=len(l)):
        yield [element for indicator, element in zip(selector, l) if indicator]

@rhettinger
Copy link
Contributor

There is already a powerset() recipe in the docs. It was contributed by
Eric Raymond.

@mdickinson
Copy link
Member

So there is. Apologies---I'll try to read more carefully next time.

@rhettinger
Copy link
Contributor

Am rejecting the OP's request for the reasons cited.

Also rejecting the request for a __len__ method on permutations.

Ezio or Mark, please open another feature request for
combinations_with_replacement() and assign to me. Will likely accept
this one and put it in when I get a chance.

Thank you to all the posters on this one.

@rhettinger
Copy link
Contributor

FWIW, I added combinations_with_replacement() in r69001 and r69004 .

@mdickinson
Copy link
Member

combinations_with_replacement addition looks good. Thank you.

I wonder whether the second argument should be constrained to be an
integer? I find the following a little surprising:

>>> list(combinations_with_replacement(range(5), -0.3))
[()]

(same behaviour with combinations and permutations). Should I open a
separate issue for this, or is it just not worth changing?

@rhettinger
Copy link
Contributor

Glad you like it.

Will meditate for a bit on the floating point input. My first thought
is that it isn't worth going through the __index__ dance to preclude
inputs that look odd.

@mdickinson
Copy link
Member

I only just noticed the DeprecationWarning that's already happening for
float inputs in 2.7. (And float inputs already raise TypeError in 3.1.)
So I agree that it's probably not worth it.

@rhettinger
Copy link
Contributor

Correction to earlier statement. It should have read:

Guido disallowed returning a len method on iterators. He expected
bool(it) to be always be True.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extension-modules C modules in the Modules dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants