+1 very useful also for me. Once in a while I have this exact scenario. Not often enough to get annoyed, but often enough that it would be nice to have.
On Tue, 28 Jul 2020 at 20:27, Noam Yorav-Raphael <noamr...@gmail.com> wrote: > > Hello, > > There's a simple function that I use many times, and I think may be a good > fit to be added to itertools. A function that gets an iterator, and if it has > exactly one element returns it, and otherwise raises an exception. This is > very useful for cases where I do some sort of query that I expect to get > exactly one result, and I want an exception to be raised if I'm wrong. For > example: > > jack = one(p for p in people if p.id == '1234') > > sqlalchemy already has such a function for queries: > https://docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.one > > more-itertools has this exact function: > https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.one > > Here is a simple implementation: > > def one(iterable): > it = iter(iterable) > try: > first = next(it) > except StopIteration: > raise ValueError("Iterator is empty") > try: > second = next(it) > except StopIteration: > return first > else: > raise ValueError("Iterator has more than one item") > > I brought this up on python-dev, but it should be discussed here. > Here is the discussion: > https://mail.python.org/archives/list/python-...@python.org/thread/D52MPKLIN4VEXBOCKVMTWAK66MAOEINY/ > > Brett Cannon said that this idea has been brought up at least twice before. I > found: > https://mail.python.org/archives/list/python-ideas@python.org/thread/FTJ6JRDTZ57HUVZ3PVIZV2NHU2NLAC4X/#RMWV3SNZ2N4KZLPKPIDE42H46QDEIVHE > > https://mail.python.org/archives/list/python-ideas@python.org/thread/REYDJFCXQNQG4SAWKELQMCGM77IZG47Q/#ITR2ILPVCKYR52U2D7RHGENASZTNVDHN > > The first thread hasn't reached any operative conclusion. The second thread > was very long, and seemed to focus mostly on another function, first(), that > doesn't check if there is more than one item. Joao S. O Bueno said that it > passed "general approval". I think that perhaps a new discussion, focused > just on one (no pun intended) function in the itertools module may reach a > conclusion. > > It was suggested that instead of an additional function, one can use iterator > unpacking: > > jack, = (p for p in people if p.id == '1234') > or > [jack] = (p for p in people if p.id == '1234') > > I still think that having a one() function would be useful, since: > 1. I think it spells the intention more clearly. It is not symbols that you > need to understand their meaning in order to understand that I expect the > iterable to have exactly one item, it's spelled in code. > 2. The exception would be easier to understand, since errors in tuple > unpacking usually mean something else. > 3. The one() function allows you to use the result inside an expression > without assigning it to a variable. Therefore, I think it encourages writing > better code. It's very easy to write: > print([p for p in people if p.id == '1234][0]) > (which has the problem of not verifying the assumption that there's no more > than one result), and I find it easier to replace _[0] with one(_) than to be > required to name a new variable, and instead of having an operation on the > iterable, change the way I'm assigning to it. > > WDYT? > > Cheers, > Noam > > > _______________________________________________ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/6OLEL4XTUWXRI7ENODKEDOYFBRVDYKI7/ > Code of Conduct: http://python.org/psf/codeofconduct/ -- Kind regards, Stefano Borini _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/FZGXJ36VUMU5XYVOSZR4AXV2FDSQLXEJ/ Code of Conduct: http://python.org/psf/codeofconduct/