Arrays/List, filters, Pytho, Ruby

Discussion in 'Python' started by LL.Snark, Feb 11, 2011.

  1. LL.Snark

    LL.Snark Guest

    Hi,

    I'm looking for a pythonic way to translate this short Ruby code :
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i=t.index {|x| x<t.first}

    If you don't know Ruby, the second line means :
    What is the index, in array t, of the first element x such that x<t[0].

    If can write it in python several ways :
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i=0
    while t>=t[0] : i+=1

    .... not pythonic I think...

    Or :
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i=[j for j in range(len(t)) if t[j]<t[0]][0]

    ....too cryptic...

    I'm using Python 3.

    Thx
    LL.Snark, Feb 11, 2011
    #1
    1. Advertising

  2. LL.Snark

    Chris Rebert Guest

    On Fri, Feb 11, 2011 at 1:24 PM, LL.Snark <> wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}
    >
    > If you don't know Ruby, the second line means :
    > What is the index, in array t, of the first element x such that x<t[0].
    >
    > If can write it in python several ways :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=0
    > while t>=t[0] : i+=1
    >
    > ... not pythonic I think...
    >
    > Or :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=[j for j in range(len(t)) if t[j]<t[0]][0]
    >
    > ...too cryptic...
    >
    > I'm using Python 3.


    My version:

    t = [6,7,8,6,7,9,8,4,3,6,7]
    i = -1
    for index, item in enumerate(t):
    if item < t[0]:
    i = index
    break

    I'm a big fan of enumerate().
    I'm sure an itertools solution is also possible.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
    Chris Rebert, Feb 11, 2011
    #2
    1. Advertising

  3. On Fri, Feb 11, 2011 at 1:43 PM, André Roberge <> wrote:
    > On Friday, February 11, 2011 5:24:15 PM UTC-4, LL.Snark wrote:
    >> Hi,
    >>
    >> I'm looking for a pythonic way to translate this short Ruby code :
    >> t=[6,7,8,6,7,9,8,4,3,6,7]
    >> i=t.index {|x| x<t.first}
    >>
    >> If you don't know Ruby, the second line means :
    >> What is the index, in array t, of the first element x such that x<t[0].
    >>
    >> If can write it in python several ways :
    >> t=[6,7,8,6,7,9,8,4,3,6,7]
    >> i=0
    >> while t>=t[0] : i+=1
    >>
    >> ... not pythonic I think...
    >>
    >> Or :
    >> t=[6,7,8,6,7,9,8,4,3,6,7]
    >> i=[j for j in range(len(t)) if t[j]<t[0]][0]
    >>
    >> ...too cryptic...
    >>

    > You could go with something like (untested)
    > t = [6,7,8,6,7,9,8,4,3,6,7]
    > for i, j in enumerate(t):
    >    if j < t[0]:
    >        break
    > else:
    >        i = 0
    >
    > ;-)
    >
    >
    >
    >> I'm using Python 3.
    >>
    >> Thx


    >>> t = [6,7,8,6,7,9,8,4,3,6,7]
    >>> generator = (element for element in t[1:] if element >= t[0])
    >>> print(next(generator))
    Dan Stromberg, Feb 11, 2011
    #3
  4. LL.Snark

    Ian Guest

    On Feb 11, 2:24 pm, "LL.Snark" <> wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}


    More Javalicious than Pythonic, but this works:

    class ComparisonPredicate:

    def __init__(self, func):
    self.func = func

    def __eq__(self, other):
    return self.func(other)

    t = [6, 7, 8, 6, 7, 9, 8, 4, 3, 6, 7]
    print(t.index(ComparisonPredicate(lambda x: x < t[0])))
    Ian, Feb 11, 2011
    #4
  5. On Fri, Feb 11, 2011 at 1:51 PM, Dan Stromberg <> wrote:
    > On Fri, Feb 11, 2011 at 1:43 PM, André Roberge <> wrote:
    >> On Friday, February 11, 2011 5:24:15 PM UTC-4, LL.Snark wrote:
    >>> Hi,
    >>>
    >>> I'm looking for a pythonic way to translate this short Ruby code :
    >>> t=[6,7,8,6,7,9,8,4,3,6,7]
    >>> i=t.index {|x| x<t.first}
    >>>
    >>> If you don't know Ruby, the second line means :
    >>> What is the index, in array t, of the first element x such that x<t[0].
    >>>
    >>> If can write it in python several ways :
    >>> t=[6,7,8,6,7,9,8,4,3,6,7]
    >>> i=0
    >>> while t>=t[0] : i+=1
    >>>
    >>> ... not pythonic I think...
    >>>
    >>> Or :
    >>> t=[6,7,8,6,7,9,8,4,3,6,7]
    >>> i=[j for j in range(len(t)) if t[j]<t[0]][0]
    >>>
    >>> ...too cryptic...
    >>>

    >> You could go with something like (untested)
    >> t = [6,7,8,6,7,9,8,4,3,6,7]
    >> for i, j in enumerate(t):
    >>    if j < t[0]:
    >>        break
    >> else:
    >>        i = 0
    >>
    >> ;-)
    >>
    >>
    >>
    >>> I'm using Python 3.
    >>>
    >>> Thx

    >
    >>>> t = [6,7,8,6,7,9,8,4,3,6,7]
    >>>> generator = (element for element in t[1:] if element >= t[0])
    >>>> print(next(generator))

    >


    Oops; a correction. Fast and concise - and if you decide you need the
    2nd or 10th, they'll be on their way as soon as you request them (lazy
    evaluation):

    >>> generator = (ind+1 for ind, element in enumerate(t[1:]) if element >= t[0])
    >>> print(next(generator))
    Dan Stromberg, Feb 11, 2011
    #5
  6. LL.Snark

    Paul Rubin Guest

    "LL.Snark" <> writes:

    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}


    from itertools import dropwhile

    t=[6,7,8,6,7,9,8,4,3,6,7]
    i = dropwhile(lambda k: t[k]>=t[0], t).next()

    Note the above can throw an exception if no suitable element is found.

    t=[6,7,8,6,7,9,8,4,3,6,7]
    i=[j for j in range(len(t)) if t[j]<t[0]][0]

    That traverses the whole list even if the desired element is near the
    beginning of the list. I don't kow if the Ruby version does the same.
    Paul Rubin, Feb 11, 2011
    #6
  7. LL.Snark

    Jon Clements Guest

    On Feb 11, 9:24 pm, "LL.Snark" <> wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}
    >
    > If you don't know Ruby, the second line means :
    > What is the index, in array t, of the first element x such that x<t[0].
    >
    > If can write it in python several ways :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=0
    > while t>=t[0] : i+=1
    >
    > ... not pythonic I think...
    >
    > Or :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=[j for j in range(len(t)) if t[j]<t[0]][0]
    >
    > ...too cryptic...
    >
    > I'm using Python 3.
    >
    > Thx


    My take (but using Python 2.x):

    import operator as op
    from functools import partial
    from itertools import islice

    t = [6,7,8,6,7,9,8,4,3,6,7]

    def first_conditional(seq, first=op.itemgetter(0), pred=op.gt):
    f = first(seq)
    cmpfunc = partial(pred, f)
    for idx, val in enumerate(islice(seq, 1, None)):
    if cmpfunc(val): return idx + 1
    return -1 # or raise an exception?


    Off top of head, so needs work, but is fairly generic.

    Jon.
    Jon Clements, Feb 11, 2011
    #7
  8. LL.Snark

    LL.Snark Guest

    On 11/02/2011 22:24, LL.Snark wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}
    >
    > If you don't know Ruby, the second line means :
    > What is the index, in array t, of the first element x such that x<t[0].
    >
    > If can write it in python several ways :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=0
    > while t>=t[0] : i+=1
    >
    > ... not pythonic I think...
    >
    > Or :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=[j for j in range(len(t)) if t[j]<t[0]][0]
    >
    > ...too cryptic...
    >
    > I'm using Python 3.



    Thx for your answers.

    May I add some comments ?

    =====================================================
    t = [6,7,8,6,7,9,8,4,3,6,7]
    i = -1
    for index, item in enumerate(t):
    if item < t[0]:
    i = index
    break

    is OK for me, while a bit too long :)
    ======================================================
    from itertools import dropwhile
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i = dropwhile(lambda k: t[k]>=t[0], t).__next__()
    (I added the __ around next. Am i true ?)

    This does not work for me.

    i is effectively 7, but 7 is the second item of the array.
    If you try :
    t=[6,8,8,6,7,9,8,4,3,6,7]
    i = dropwhile(lambda k: t[k]>=t[0], t).__next__()
    You will get 8.

    I guess this is because k is a value of the array, not an index.
    In the first example, we compare t[6], then t[7], then t[8], t[6], t[7]
    etc... to t[0].
    (It happens that the first item of the list is dropped... then the first
    element of the resulting list is 7... the answer... but it was just luck)

    =====================================================
    The javalicious one :

    class ComparisonPredicate:
    def __init__(self, func):
    self.func = func
    def __eq__(self, other):
    return self.func(other)

    t = [6, 7, 8, 6, 7, 9, 8, 4, 3, 6, 7]
    print(t.index(ComparisonPredicate(lambda x: x < t[0])))

    It took me some time to understand :)
    It's a shame there is no built-in object like ComparisonPredicate,
    because the line t.index(ComparisonPredicate(lambda x: x < t[0])) looks
    good to me.

    ===================================================
    Finally, the other enumerate solution may be written like this :
    t = [6,7,8,6,7,9,8,4,3,6,7]
    for i, j in enumerate(t):
    if j < t[0]: break
    else : i=-1
    Quite short.

    =================================================
    Finally, with your solutions, I build another one. Here it is :
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i,j=filter(lambda x: x[1]<t[0],enumerate(t)).__next__()

    Or :
    from itertools import dropwhile
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i,j=dropwhile(lambda x: x[1]>=t[0],enumerate(t)).__next__()

    Or else :
    t=[6,7,8,6,7,9,8,4,3,6,7]
    t.index(filter(lambda x: x<t[0],t).__next__())

    The last one behaves like the Ruby one, if a value is found. If no walue
    is found, the Python code raises a StopException. With the Ruby code, i
    is nil.

    Is there another way to access the first item of an iterator ?
    ( __next__() is ugly )

    ======================================================
    Paul, the Ruby version stops when it finds the first matching element
    t=[6,7,8,6,7,9,8,4,3,6,7]
    i=t.index {|x| x<t.first}

    (I figured this out by making a 1 000 000 elements array. It was faster
    with a matching value at the beginning of the array)

    Many thanks for your answers
    LL.Snark, Feb 12, 2011
    #8
  9. LL.Snark

    Terry Reedy Guest

    On 2/11/2011 4:24 PM, LL.Snark wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}
    >
    > If you don't know Ruby, the second line means :
    > What is the index, in array t, of the first element x such that x<t[0].


    What does Ruby do if there is no such element?
    For Python, the answer should be either None or ValueError.

    >
    > If can write it in python several ways :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=0
    > while t>=t[0] : i+=1


    This will raise IndexError when i gets too big.

    > ... not pythonic I think...
    >
    > Or :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=[j for j in range(len(t)) if t[j]<t[0]][0]


    This will raise IndexError if the list is empty.

    --
    Terry Jan Reedy
    Terry Reedy, Feb 12, 2011
    #9
  10. LL.Snark

    Bruno Piguet Guest

    On 11 fév, 22:24, "LL.Snark" <> wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}


    I'm thinking of two methods, depending on the length of the list, and
    the fact that you wish (or not) to scan the whole list.

    The first one, quite simple, but scanning the whole list :
    t=[6,7,8,6,7,9,8,4,3,6,7]
    [x<t[0] for x in t].index(True)

    The alternative method, which will stop at the first element matching
    the condition, but which might be less readable :
    next(i for i, x in enumerate(t) if x<t[0])

    If there is a risk that no element match the condition, and you don't
    want an StopIteration exception, use the second optionnal argument of
    next :
    next((i for i, x in enumerate(t) if x>1000), "not found")
    or
    next((i for i, x in enumerate(t) if x>1000), None)
    or whatever matches your needs.
    Note that if you use the second optionnal argument of next, you'll
    need an additional pair of parentheses around
    the generator expression which is the first argument of next.

    Bruno.
    Bruno Piguet, Feb 12, 2011
    #10
  11. LL.Snark

    DouhetSukd Guest

    On Feb 11, 1:24 pm, "LL.Snark" <> wrote:
    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}
    >
    > If you don't know Ruby, the second line means :
    > What is the index, in array t, of the first element x such that x<t[0].
    >
    > If can write it in python several ways :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=0
    > while t>=t[0] : i+=1
    >
    > ... not pythonic I think...
    >
    > Or :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=[j for j in range(len(t)) if t[j]<t[0]][0]
    >
    > ...too cryptic...
    >
    > I'm using Python 3.
    >
    > Thx


    [i for i,v in enumerate(t) if v < t[0]][0:1]

    empty list if no match.
    DouhetSukd, Feb 12, 2011
    #11
  12. "LL.Snark" <> writes:

    > Hi,
    >
    > I'm looking for a pythonic way to translate this short Ruby code :
    > t=[6,7,8,6,7,9,8,4,3,6,7]
    > i=t.index {|x| x<t.first}
    >


    In Python3:

    >>> t = [6,7,8,6,7,9,8,4,3,6,7]
    >>> next(filter(t[0].__gt__, t))

    4

    --
    Arnaud
    Arnaud Delobelle, Feb 12, 2011
    #12
  13. Arnaud Delobelle <> writes:

    > "LL.Snark" <> writes:
    >
    >> Hi,
    >>
    >> I'm looking for a pythonic way to translate this short Ruby code :
    >> t=[6,7,8,6,7,9,8,4,3,6,7]
    >> i=t.index {|x| x<t.first}
    >>

    >
    > In Python3:
    >
    >>>> t = [6,7,8,6,7,9,8,4,3,6,7]
    >>>> next(filter(t[0].__gt__, t))

    > 4


    Oops! I realised my mistake the moment I sent the reply. You can do this
    to get the index:

    >>> next(i for i, x in enumerate(t) if x < t[0])

    7

    --
    Arnaud
    Arnaud Delobelle, Feb 12, 2011
    #13
  14. LL.Snark

    LL.Snark Guest

    On 12/02/2011 04:49, Terry Reedy wrote:
    > On 2/11/2011 4:24 PM, LL.Snark wrote:
    >> Hi,
    >>
    >> I'm looking for a pythonic way to translate this short Ruby code :
    >> t=[6,7,8,6,7,9,8,4,3,6,7]
    >> i=t.index {|x| x<t.first}
    >>
    >> If you don't know Ruby, the second line means :


    >
    > What does Ruby do if there is no such element?
    > For Python, the answer should be either None or ValueError.


    Ruby code :
    # What is the index, in array t,
    # of the first element x such that x<t[0].
    t=[6,7,8,6,7,9,8,9,4,3,6,7]
    i=t.index {|x| x<t.first}

    Stops when the first value is found.
    If no value is found, then i is nil (None equivalent)

    (The answer if index 8, value 4)

    Here is the last summary (Python 3) :
    =====================================================
    t=[6,7,8,6,7,9,8,9,4,3,6,7]

    and then... :
    =======================================================
    for i, j in enumerate(t):
    if j < t[0]: break
    else : i=-1

    # Now i==8 and j==4
    # i==-1 if no value is found
    ======================================================
    class ComparisonPredicate:
    def __init__(self, func):
    self.func = func
    def __eq__(self, other):
    return self.func(other)
    t.index(ComparisonPredicate(lambda x: x < t[0]))
    => 8
    # Raises an exception if no value found
    ======================================================
    The following solutions raise a StopIteration exception if no value is
    found. See below how to use the second argument of next

    next(filter(lambda x: x[1]<t[0],enumerate(t)))
    => (8,4)

    from itertools import dropwhile
    next(dropwhile(lambda x: x[1]>=t[0],enumerate(t)))
    => (8,4)

    Or if you don't like enumerate :
    next(filter(lambda x: x<t[0],t))
    => 4
    t.index(next(filter(lambda x: x<t[0],t))
    => 8

    next(filter(t[0].__gt__, t))
    => 4
    ================================================================
    Generators and enumerate :

    next(i for i,v in enumerate(t) if v<t[0])
    => 8

    If no values exists, this raises an exception. Second argument of next
    can help you :

    next((i for i,v in enumerate(t) if v<t[0]),None)
    => 8 # returns None if no value found
    ===========================================================

    If you use lists instead of generators, it works, but you have to go
    across the whole array :

    [x<t[0] for x in t].index(True)
    => 8

    [i for i,v in enumerate(t) if v < t[0]]
    => [ 8, 9 ] (indices of all array values less than t[0]

    If you are only interested in the first value :
    [i for i,v in enumerate(t) if v < t[0]][0]
    => 8 (but raises an exception if the list if no value is found)
    [i for i,v in enumerate(t) if v < t[0]][0:1]
    => [8] (return an empty list if no value is found)

    Keep in mind that, even if you just select the first value [0] or [0:1],
    you go across the whole array t

    =================================================
    I found it very interesting to read all these short lines of code.
    Thanks to : Chris, Ian, Paul, Jon, Therry, Bruno, Arnaud and people that
    have no name (like me...)


    next(((i,v) for i,v in enumerate(t) if v<t[0]),None)
    LL.Snark, Feb 14, 2011
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Leo
    Replies:
    4
    Views:
    351
    Skip Montanaro
    Oct 14, 2003
  2. Dieter Vanderelst

    using the Filters DLL (image filters)

    Dieter Vanderelst, Feb 15, 2006, in forum: Python
    Replies:
    1
    Views:
    408
    Michele Petrazzo
    Feb 15, 2006
  3. jgm
    Replies:
    0
    Views:
    272
  4. makerjoe

    pytho servlet engine

    makerjoe, Oct 24, 2006, in forum: Python
    Replies:
    3
    Views:
    295
    makerjoe
    Oct 24, 2006
  5. Philipp
    Replies:
    21
    Views:
    1,109
    Philipp
    Jan 20, 2009
Loading...

Share This Page