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

Update combinations docs #19732

Merged
merged 1 commit into from
May 28, 2020
Merged

Update combinations docs #19732

merged 1 commit into from
May 28, 2020

Conversation

ruaridhw
Copy link
Contributor

@ruaridhw ruaridhw commented Apr 27, 2020

  • The order of the iterable is not modified within combinations() as these docs imply
  • Instead, the order of elements is used as-is
>>> from itertools import combinations
>>> list(combinations(list(range(4)), 2))
## [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
>>> list(combinations(reversed(list(range(4))), 2))
## [(3, 2), (3, 1), (3, 0), (2, 1), (2, 0), (1, 0)]

I would have expected that should these docs be true, the last line starts with (0, 1) or perhaps (2, 3) if we are to interpret that the tuple itself is sorted. Instead, the order of iterable is used (as expected).

@ruaridhw ruaridhw requested a review from rhettinger as a code owner April 27, 2020 07:48
@bedevere-bot bedevere-bot added docs Documentation in the Doc dir awaiting review labels Apr 27, 2020
@the-knights-who-say-ni
Copy link

Hello, and thanks for your contribution!

I'm a bot set up to make sure that the project can legally accept this contribution by verifying everyone involved has signed the PSF contributor agreement (CLA).

Recognized GitHub username

We couldn't find a bugs.python.org (b.p.o) account corresponding to the following GitHub usernames:

@ruaridhw

This might be simply due to a missing "GitHub Name" entry in one's b.p.o account settings. This is necessary for legal reasons before we can look at this contribution. Please follow the steps outlined in the CPython devguide to rectify this issue.

You can check yourself to see if the CLA has been received.

Thanks again for the contribution, we look forward to reviewing it!

@ruaridhw
Copy link
Contributor Author

ruaridhw commented Apr 27, 2020

Found these docs a little misleading, please let me know if this requires a BPO entry.

The same can be said of combinations_with_replacement(), permutations(), and product() so if this is applicable, probably best to add changes to those docs as well.

Copy link
Contributor

@remilapeyre remilapeyre left a comment

Choose a reason for hiding this comment

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

Hi @ruaridhw, thanks for taking the time to improve the documentation.

I'm not sure this new wording is much better though, I think we should keep the reference to the lexicographic order. Maybe we should move the note that elements are used based on their order and not their value here instead?

@ruaridhw
Copy link
Contributor Author

ruaridhw commented Apr 27, 2020

I think we should keep the reference to the lexicographic order

@remilapeyre, what was your reasoning for this? Personally, this was the confusing part for me and the only reference that I'd like to remove. I think I'm missing something because I can't see how these methods care about lexicographic order at all.

Take for example, a completely unsortable class:

from itertools import combinations


class NotSortable:
    def __init__(self, id_):
        self.id = id_

    def __repr__(self):
        return f'{self.id}'


sorted([NotSortable(3), NotSortable(2)])
## TypeError: '<' not supported between instances of 'NotSortable' and 'NotSortable'
combs = list(combinations([NotSortable(3), NotSortable(2), NotSortable(4), NotSortable(1)], 2))
print(combs)
## [(3, 2), (3, 4), (3, 1), (2, 4), (2, 1), (4, 1)]

Surely any "lexicographic order" (or any ordering for that matter other than the one provided) of this input iterable is undefined?

@remilapeyre
Copy link
Contributor

With this unsortable class we can have the objects

a = NotSortable(3)
b = NotSortable(2)
c = NotSortable(4)
d = NotSortable(1)

and we can define pos() so that

pos(a) = 1
pos(b) = 2
pos(c) = 3
pos(d) = 4

and pos() defines an order over {a, b, c, d} and combinations() will output pairs in lexicographic order. It's just not the order defined by NotSortable.__lt__() but the one defined by list.index(). It can be confusing but it seems to me that it is correct and we should maybe improve the phrasing but not remove the whole paragraph.

@ruaridhw
Copy link
Contributor Author

ruaridhw commented Apr 27, 2020

Hmmm that does seem highly confusing. My point is that there are no cases where it output order is defined by anything other than list.index(). Hence we should explicitly state this.

Stating "combinations are emitted in lexicographic sort order" reads to me as if the elements of the iterable or the iterable itself must define a lexicographic sort order and this is not the case. Especially because if the elements do define a lexicographic sort order (eg. str), this is not the order of the output pairs:

>>> print(list(combinations('dbca', 2)))
## [('d', 'b'), ('d', 'c'), ('d', 'a'), ('b', 'c'), ('b', 'a'), ('c', 'a')]

@rhettinger rhettinger self-assigned this Apr 28, 2020
input *iterable* is sorted, the combination tuples will be produced
in sorted order.
The combination tuples are emitted in the order of the input
*iterable*.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please keep the second sentence.

@csabella
Copy link
Contributor

@ruaridhw, please address the code review comments. Thank you!

@csabella csabella changed the base branch from 3.8 to master May 26, 2020 11:36
@csabella csabella changed the base branch from master to 3.8 May 26, 2020 11:37
@csabella
Copy link
Contributor

@ruaridhw, thank you for making the change. I apologize for not seeing this before, but I just noticed you made this PR against the 3.8 branch instead of the master branch. Generally, all of our PRs are against master and then we have a bot that will backport changes to other releases. Based on that, please change this to be over the master branch. It's a little more involved than just changing the base branch. Thanks!

- The order of the iterable is not modified within `combinations()` as these docs imply
- Instead, the order of elements is used as-is
@ned-deily ned-deily changed the title Update combinations docs Update itertools combinations docs May 28, 2020
@ned-deily ned-deily changed the title Update itertools combinations docs [3.9] Update combinations docs May 28, 2020
@ned-deily ned-deily changed the title [3.9] Update combinations docs Update combinations docs May 28, 2020
@rhettinger
Copy link
Contributor

Attempting to restart the bots by closing and reopening.

@rhettinger rhettinger closed this May 28, 2020
@rhettinger rhettinger reopened this May 28, 2020
@rhettinger rhettinger merged commit 5e0ed8a into python:master May 28, 2020
@miss-islington
Copy link
Contributor

Thanks @ruaridhw for the PR, and @rhettinger for merging it 🌮🎉.. I'm working now to backport this PR to: 3.8, 3.9.
🐍🍒⛏🤖

@bedevere-bot
Copy link

GH-20501 is a backport of this pull request to the 3.9 branch.

@bedevere-bot
Copy link

GH-20502 is a backport of this pull request to the 3.8 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request May 28, 2020
(cherry picked from commit 5e0ed8a)

Co-authored-by: Ruaridh Williamson <ruaridhw@users.noreply.github.com>
@ruaridhw ruaridhw deleted the patch-1 branch May 29, 2020 07:39
CuriousLearner added a commit to CuriousLearner/cpython that referenced this pull request May 30, 2020
* 'master' of github.com:python/cpython: (497 commits)
  bpo-40061: Fix a possible refleak in _asynciomodule.c (pythonGH-19748)
  bpo-40798: Generate a different message for already removed elements (pythonGH-20483)
  closes bpo-29017: Update the bindings for Qt information with PySide2 (pythonGH-20149)
  bpo-39885: Make IDLE context menu cut and copy work again (pythonGH-18951)
  bpo-29882: Add an efficient popcount method for integers (python#771)
  Further de-linting of zoneinfo module (python#20499)
  bpo-40780: Fix failure of _Py_dg_dtoa to remove trailing zeros (pythonGH-20435)
  Indicate that abs() method accept argument that implement __abs__(), just like call() method in the docs (pythonGH-20509)
  bpo-39040: Fix parsing of email mime headers with whitespace between encoded-words. (pythongh-17620)
  bpo-40784: Fix sqlite3 deterministic test (pythonGH-20448)
  bpo-30064: Properly skip unstable loop.sock_connect() racing test (pythonGH-20494)
  Note the output ordering of combinatoric functions (pythonGH-19732)
  bpo-40474: Updated coverage.yml to better report coverage stats (python#19851)
  bpo-40806: Clarify that itertools.product immediately consumes its inpt (pythonGH-20492)
  bpo-1294959: Try to clarify the meaning of platlibdir (pythonGH-20332)
  bpo-37878: PyThreadState_DeleteCurrent() was not removed (pythonGH-20489)
  bpo-40777: Initialize PyDateTime_IsoCalendarDateType.tp_base at run-time (pythonGH-20493)
  bpo-40755: Add missing multiset operations to Counter() (pythonGH-20339)
  bpo-25920: Remove socket.getaddrinfo() lock on macOS (pythonGH-20177)
  bpo-40275: Fix test.support.threading_helper (pythonGH-20488)
  ...
in sorted order.
The permutation tuples are emitted in lexicographic ordering according to
the order of the input *iterable*. So, if the input *iterable* is sorted,
the combination tuples will be produced in sorted order.
Copy link
Member

Choose a reason for hiding this comment

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

Should "combination tuples" be "permutation tuples" here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, good spot 🤦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir skip issue skip news
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants