Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6141125
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T18:12:25+00:00 2026-05-23T18:12:25+00:00

I keep thinking there should be a function for this, but I’ve searched the

  • 0

I keep thinking there should be a function for this, but I’ve searched the likely places (google, itertools docs, list methods, other SO questions), but nowhere found quite what I was looking for.

Naive and working implementation:

def split_at_first_false(pred, seq):
    first = []
    second = []
    true_so_far = True
    for item in seq:
        if true_so_far and pred(item):
            first.append(item)
        else:
            true_so_far = False
            second.append(item)
    return first, second

print split_at_first_false(str.isalpha, "abc1a2b")
# (['a', 'b', 'c'], ['1', 'a', '2', 'b'])

It works, but it doesn’t feel right. There should be a better way to do this!

EDIT: I ended up with using a slightly modified version of senderle’s final suggestion after reviewing the answers:

from itertools import chain

def split_at_pred(pred, seq):
    head = []
    it = iter(seq)
    for i in it:
        if not pred(i):
            head.append(i)
        else:
            return iter(head), chain([i], it)
    return iter(head), iter([])

It’s short and elegant, output is two iterators no matter the input (strings, lists, iterators), and as a bonus, it even works with the following input:

from itertools import count
split_at_pred(lambda x: x == 5, count())

The other solutions, those that work at all with iterators, will run out of memory with this input. (Note that this is just a bonus. Infinite iterators was something I hadn’t even considered when I wrote this question)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T18:12:26+00:00Added an answer on May 23, 2026 at 6:12 pm

    This seems like a job for itertools.

    >>> first = list(itertools.takewhile(str.isalpha, l))
    >>> second = list(itertools.dropwhile(str.isalpha, l))
    >>> first
    ['a', 'b', 'c']
    >>> second
    ['1', 'a', '2', 'b']
    

    This needs to be altered if l is an iterator rather than a sequence.

    >>> def bisect_iter(pred, i):
    ...     i1, i2 = itertools.tee(i)
    ...     return itertools.takewhile(pred, i1), itertools.dropwhile(pred, i2)
    ... 
    >>> i1, i2 = bisect_iter(str.isalpha, iter(l))
    >>> list(i1)
    ['a', 'b', 'c']
    >>> list(i2)
    ['1', 'a', '2', 'b']
    

    The downside of tee is that the initial values are cached and tested twice (by both takewhile and dropwhile). That’s wasteful. But caching values is unavoidable if you want to both accept and return iterators.

    However, if you can return lists from an iterator, I can think of one solution that doesn’t make extra copies or tests, and it’s very close to yours:

    >>> def bisect_iter_to_list(pred, it):
    ...     l1 = []
    ...     for i in it:
    ...         if pred(i):
    ...             l1.append(i)
    ...         else:
    ...             l2 = [i]
    ...             l2.extend(it)
    ...     return l1, l2
    ... 
    >>> bisect_iter_to_list(str.isalpha, iter(l))
    (['a', 'b', 'c'], ['1', 'a', '2', 'b'])
    

    The only sneaky bit is that where there would normally be a break statement (i.e. after the else clause), I’ve simply consumed the iterator, causing the for loop to terminate early.

    Finally, if you still want to return iterators, but don’t want to do extra tests, here’s a variation on the above that I believe is optimal.

    >>> def bisect_any_to_iter(pred, it):
    ...     it = iter(it)
    ...     head = []
    ...     for i in it:
    ...         if pred(i):
    ...             head.append(i)
    ...         else:
    ...             tail = itertools.chain([i], it)
    ...             break
    ...     return iter(head), tail
    ... 
    >>> a, b = bisect_iter_to_iter(str.isalpha, iter(l))
    >>> list(a)
    ['a', 'b', 'c']
    >>> list(b)
    ['1', 'a', '2', 'b']
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Maybe I should just make this a public member, but I keep thinking it
I want to be able to replace style="STUFF" I keep thinking that this is
I'm pretty sure this can be done without going into a function but I
I have searched for this online, but am still a bit confused (as I'm
I'd like to keep my database clean of stale almost-accounts, and I was thinking
Right now, I keep all of my projects on my laptop. I'm thinking that
Keep in mind that I'm not looking for a list of current browsers to
Keep getting this error after inserting a subdatasheet into a query and trying to
I keep getting tasks that are above my skill level. How can I address this without coming accross as grossly incompetent?
I keep running across this loading image http://georgia.ubuntuforums.com/images/misc/lightbox_progress.gif which seems to have entered into

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.