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[i]>=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





--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to