views:

76

answers:

3

Given the array a = [1,1,12,3,5,8,13,21] I can slice off the first 3 elements like a[:3] giving [1,1,2]. What I want is to slice off up to the element of vlaue i (e.g. if i=8 I want [1,1,12,3,5,8] or [1,1,12,3,5] (I can work with either)).

This works:

return a[:a.index(i)]

but only if I give it a value that's in the array.

Is there a clean built in way to do this that does something sane on the missing value case?

A: 

Assuming the array is sorted, use a binary search. The function is in the bisect module.

from bisect import bisect_right
a[:bisect_right(a, value)]
David Zaslavsky
Sorry, the array is unordered. See edit of title.
BCS
It was misleading to use a sorted example in the question, then.
David Zaslavsky
Sorry, it was the first series to come to mind after 1,2,3,...
BCS
A: 

Create a generator, and use that:

a = [1,1,2,3,5,8,13,21]

def _gen(listing, cutoff):
    for i in listing:
        if i == cutoff:
            return

        yield i

new_a = list(_gen(a, 5))

... or, if you really want a slice ...

for i, val in enumerate(a):
    if val == cutoff:
        break

new_a = a[:i]
Chris B.
Sorry, the array is unordered. See edit of title.
BCS
+5  A: 
  1. That's a list.

  2. Try

    >>> a = [1,1,2,3,5,8,13,21]
    >>> import itertools
    >>> for x in itertools.takewhile(lambda val: val != 8, a):
    ...     print x
    ...
    1
    1
    2
    3
    5
    
Mike Graham
+1 for takewhile though I would say `val != 6` is more appropriate for an unsorted list.
Mark Byers
`val != 6` returns the entire list when `6` is missing.
Chris B.
@Chris: that's ok. As would be returning `[]`. But using `<`, `>`, etc. would be wrong as then it would stop on a 20.
BCS
@BCS: In other words, you don't care _what_ you get back, you just want to avoid an exception. So why don't you just _catch_ the exception?
Chris B.
@Chris, I need a value so using a catch would make the code 5 times as long and would be no more readable (at best) than checking for that case with an if.
BCS
Five times as long? `try: return a[:a.index(i)]; except: return []`
Chris B.
Returning meaningless values rather than raising exceptions when under exceptional circumstances sounds like a bad idea.
Mike Graham
@Chris: Is that a statement or an expression? Given that it will be replacing an expression (see Mike's answer) that doubles the size. Also I can take a million line C program and remove most of the \n's. That doesn't make it a l line program.
BCS
@Mike, In general, you are correct. In my case the choice is more or less arbitrary and either option is reasonable.
BCS
Number of lines is not typically a good thing to optimise for.
Mike Graham
@Mike, "All else being equal"... Unless you/I can point at something (anything) that makes it *worse*, I'll generally prefer shorter code as it tends to more closely match what I want to say.
BCS