Arrays/List, filters, Pytho, Ruby

LL.Snark ll.snark at gmail.com
Fri Feb 11 19:11:31 EST 2011


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








More information about the Python-list mailing list