2011-02-11 27 views
15

¿Hay alguna manera de volver a escribir esto más elegante? Creo que es un mal código y debe ser refactorizado.Ruby: ¿Cómo encontrar el índice del elemento de matriz mínimo?

>> a = [2, 4, 10, 1, 13] 
=> [2, 4, 10, 1, 13] 
>> index_of_minimal_value_in_array = a.index(a.min) 
=> 3 
+3

En serio? 'a.index (a.min)'? –

+1

No estoy seguro de esto. Quizás es mi ansiedad excesiva. – kyrylo

+1

Diría que esto es casi tan limpio como se puede, así que no hay necesidad de "refactorizar" aquí. – fresskoma

Respuesta

5

Sería interesante leer sobre otras situaciones (encontrar todas y sólo una mínima último elemento).

ary = [1, 2, 1] 

# find all matching elements' indexes 
ary.each.with_index.find_all{ |a,i| a == ary.min }.map{ |a,b| b } # => [0, 2] 
ary.each.with_index.map{ |a, i| (a == ary.min) ? i : nil }.compact # => [0, 2] 

# find last matching element's index 
ary.rindex(ary.min) # => 2 
+0

¿Hay alguna diferencia apreciable entre: ary.each.with_index ... y ary.each_with_index ...? Encontré que cada_con_índice no está documentado. Pero ary.methods.grep (/ each_with_index /); es verdad. – kyrylo

+1

Ambos están documentados en [Enumerator] (http://rubydoc.info/stdlib/core/1.9.2/Enumerator), de los que Array hereda. 'each.with_index' toma la matriz y agrega un índice formando una matriz de matrices, con las matrices internas que contienen los elementos originales más índices. Entonces puede pasar eso a otros transformadores como 'map'. 'each_with_index' quiere iterar sobre las matrices de matrices. Es una diferencia sutil, pero no quería un bucle 'cada', quería transformarlo. –

+0

Este rendimiento del algoritmo será extremadamente bajo – texasbruce

7

Este atraviesa la matriz solamente una vez mientras que ary.index(ary.min) atravesaría dos veces:

ary.each_with_index.inject(0){ |minidx, (v,i)| v < a[minidx] ? i : minidx } 
+3

'ary.index (ary.min)' es mucho más simple de leer. – kyrylo

33

Creo que esto va a atravesar la matriz sólo una vez y sigue siendo fácil de leer:

ary = [2,3,4,5,1]  # => [2,3,4,5,1] 
ary.each_with_index.min # => [1, 4] 
         # where 1 is the element and 4 is the index 
+1

Solución limpia. Desafortunadamente 'Array # last' lo hace feo (' ary.each_with_index.min.last'). – kyrylo

3

En realidad me gusta la respuesta de @andersonvom, solo necesita repetir el conjunto una vez y aún obtener el índice.

Y en caso de que no desee utilizar ary.each_with_index.min, esto es lo que puede hacer:

ary = [2,3,4,5,1]            # => [2,3,4,5,1] 
_, index_of_minimal_value_in_array = ary.each_with_index.min # => [1, 4] 
index_of_minimal_value_in_array        # => 4 
Cuestiones relacionadas