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