86

I'm wondering if there's a reason that there's no first(iterable) in the Python built-in functions, somewhat similar to any(iterable) and all(iterable) (it may be tucked in a stdlib module somewhere, but I don't see it in itertools). first would perform a short-circuit generator evaluation so that unnecessary (and a potentially infinite number of) operations can be avoided; i.e.

def identity(item):
    return item

def first(iterable, predicate=identity):
    for item in iterable:
        if predicate(item):
            return item
    raise ValueError('No satisfactory value found')

This way you can express things like:

denominators = (2, 3, 4, 5)
lcd = first(i for i in itertools.count(1)
    if all(i % denominators == 0 for denominator in denominators))

Clearly you can't do list(generator)[0] in that case, since the generator doesn't terminate.

Or if you have a bunch of regexes to match against (useful when they all have the same groupdict interface):

match = first(regex.match(big_text) for regex in regexes)

You save a lot of unnecessary processing by avoiding list(generator)[0] and short-circuiting on a positive match.

cdleary
  • 69,512
  • 53
  • 163
  • 191
  • Just a note: I realize that the predicate kwarg is redundant with the generator capabilities. I just wanted to be thorough in defining what "first" really meant. – cdleary Jul 03 '09 at 00:12
  • related: [Python: find first element in a sequence that matches a predicate](http://stackoverflow.com/q/8534256/4279) – jfs Aug 15 '13 at 07:35
  • Does this answer your question? [Find first element in a sequence that matches a predicate](https://stackoverflow.com/questions/8534256/find-first-element-in-a-sequence-that-matches-a-predicate) – Flimm Jan 19 '22 at 08:24

6 Answers6

57

In Python 2, if you have an iterator, you can just call its next method. Something like:

>>> (5*x for x in xrange(2,4)).next()
10

In Python 3, you can use the next built-in with an iterator:

>>> next(5*x for x in range(2,4))
10
Flimm
  • 136,138
  • 45
  • 251
  • 267
liori
  • 40,917
  • 13
  • 78
  • 105
  • 2
    A general solution for all iterables (e.g. for both lists and generators) in Python 2.6 and up is `next(iter(xs))`. In Python 2.5 you can do `iter(xs).next()`. – sah Feb 20 '12 at 00:57
  • 11
    I don't understand this answer. The 'first' shown in the question skips over the initial elements of the sequence that are 'falsy' (as defined by bool(predicate(item))). I thought that was the point. 'next()'doesn't do this. I am confused. – Jonathan Hartley Mar 16 '13 at 16:12
  • 4
    @JonathanHartley: the point is that having next() and a generic way to build a filtered sequence (e.g. using `itertools.ifilter()` or `(… for … in … if condition)`, combining them is not enough effort to justify having another built-in tool. Note that OP's regex example is just `next(regex for regex in regexes if regex.match(big_text))`. – liori Mar 16 '13 at 17:02
  • Right. That makes sense. Thanks liori. – Jonathan Hartley Mar 20 '13 at 13:17
  • 6
    OP's example returns something differently than `next(regex for regex in regexes if regex.match(big_text))`; it returns the results of regex.match(big_text). How does one do that without first() ? `next(regex.match(big_text) for regex in regexes if regex.match(big_text))` is redundant. `next(ifilter(imap(lambda x: x.match(big_text), regexes)))` seems overly complex, compared to first. – pjz May 06 '13 at 15:11
  • 2
    @JonathanHartley and @ pjz are right. So I have to downvote (and scold all upvoters for not taking this into account ;-) ). See my answer for more details, please. – Alfe Aug 14 '13 at 07:57
  • 2
    Note that this is not idempotent. (Meaning that `next()` will only return the first element the first time it is called). – cowlinator Nov 09 '21 at 02:57
  • Sadly, next() works only on iterators, not iterables. The OP is looking for an equivalent that works on iterables (and so am I). For example, next(range(10)) and next({1: 2}.values()) both throw exceptions. – Jeff Schwab Jul 14 '23 at 11:49
21

There's a Pypi package called “first” that does this:

>>> from first import first
>>> first([0, None, False, [], (), 42])
42

Here's how you would use to return the first odd number, for example:

>> first([2, 14, 7, 41, 53], key=lambda x: x % 2 == 1)
7

If you just want to return the first element from the iterator regardless of whether is true or not, do this:

>>> first([0, None, False, [], (), 42], key=lambda x: True)
0

It's a very small package: it only contains this function, it has no dependencies, and it works on Python 2 and 3. It's a single file, so you don't even have to install it to use it.

In fact, here's almost the entire source code (from version 2.0.1, by Hynek Schlawack, released under the MIT licence):

def first(iterable, default=None, key=None):
    if key is None:
        for el in iterable:
            if el:
                return el
    else:
        for el in iterable:
            if key(el):
                return el
    return default
Flimm
  • 136,138
  • 45
  • 251
  • 267
  • 12
    Nice. But implementing it by yourself will take about three lines of code. This hardly justifies the overhead of installing a complete package (introducing all the portability problems etc.). The question remains: Why isn't this part of the built-ins in Python? Or what is the cleanest, most Pythonic way to spell this out using built-in Python structures? – Alfe Aug 14 '13 at 08:27
  • 2
    @Alfe: Using packages is clean and Pythonic. As for why it isn't a built-in, that's not a question for Stack Overflow, since it can't possibly be answered by anyone who isn't a core committer. – Flimm Aug 14 '13 at 23:03
  • 2
    Okay, then let me put it this way: How would you implement the `first` function from module `first`? When I ask why this isn't a built-in, I do this because I suspect that there is a Pythonic way to express this using more general features like list comprehensions etc. which make it redundant enough to leave it out. – Alfe Aug 14 '13 at 23:27
  • 2
    @Alfie: Fair enough. The other answers attempt to do that, but as you can see, the result isn't that pretty, and I'm sure some people who are in a position to easily install modules will find `first` useful. I've included the source code for the function for interest. – Flimm Aug 15 '13 at 07:29
  • "But implementing it by yourself will take about three lines of code" -> well, i looked at at least a dozen answers to this functionnality, and all of them seems to involve at least a few lines with either a loop, or a function with yield, or whatever seemly magic pythonic trick from a python novice. In ruby, you do mylist.first or myiterator.first and it works. Simple, errorproof and the most readable – Alex F Nov 24 '17 at 13:35
  • "a little copying is better than a little dependency" - I do not think installing a package to use a one-liner function from it is a sensible thing to do. – pjboro Mar 12 '22 at 14:16
12

I asked a similar question recently (it got marked as a duplicate of this question by now). My concern also was that I'd liked to use built-ins only to solve the problem of finding the first true value of a generator. My own solution then was this:

x = next((v for v in (f(x) for x in a) if v), False)

For the example of finding the first regexp match (not the first matching pattern!) this would look like this:

patterns = [ r'\d+', r'\s+', r'\w+', r'.*' ]
text = 'abc'
firstMatch = next(
  (match for match in
    (re.match(pattern, text) for pattern in patterns)
   if match),
  False)

It does not evaluate the predicate twice (as you would have to do if just the pattern was returned) and it does not use hacks like locals in comprehensions.

But it has two generators nested where the logic would dictate to use just one. So a better solution would be nice.

Community
  • 1
  • 1
Alfe
  • 56,346
  • 20
  • 107
  • 159
8

There is a "slice" iterator in itertools. It emulates the slice operations that we're familiar with in python. What you're looking for is something similar to this:

myList = [0,1,2,3,4,5]
firstValue = myList[:1]

The equivalent using itertools for iterators:

from itertools import islice
def MyGenFunc():
    for i in range(5):
        yield i

mygen = MyGenFunc()
firstValue = islice(mygen, 0, 1)
print firstValue 
Zoran Pavlovic
  • 1,166
  • 2
  • 23
  • 38
6

There's some ambiguity in your question. Your definition of first and the regex example imply that there is a boolean test. But the denominators example explicitly has an if clause; so it's only a coincidence that each integer happens to be true.

It looks like the combination of next and itertools.ifilter will give you what you want.

match = next(itertools.ifilter(None, (regex.match(big_text) for regex in regexes)))
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
A. Coady
  • 54,452
  • 8
  • 34
  • 40
  • True, if the answer were zero we'd have a problem. The `next(iterator)` was the answer I was missing. – cdleary Jul 03 '09 at 02:12
4

Haskell makes use of what you just described, as the function take (or as the partial function take 1, technically). Python Cookbook has generator-wrappers written that perform the same functionality as take, takeWhile, and drop in Haskell.

But as to why that's not a built-in, your guess is as good as mine.

Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
  • 3
    Such functions ("builtins" in terms of type and speed!) are in the itertools module of the standard library -- just like (e.g.) regular expressions are in the re module, math functions in the math module, etc. Always hard to decide what's best presented in the main namespace -- Perl has REs as built-ins, Fortran has SIN and COS &c, Haskell keeps there names such as take... Python prefers to have all of these groups of names in standard library modules. – Alex Martelli Jul 03 '09 at 01:20
  • 3
    wouldn't the Haskell equivalent of _first_ be _head_? "take 1" returns a list, not an element. – tokland Jul 13 '10 at 19:41