2011-02-11 19 views
15

Czy istnieje sposób na przepisanie tego bardziej eleganckiego? Myślę, że to zły kawałek kodu i powinien być refaktoryzowany.Ruby: Jak znaleźć indeks minimalnego elementu tablicy?

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

Poważnie? 'a.index (a.min)'? –

+1

Nie jestem tego pewien. Może to mój nadmierny niepokój. – kyrylo

+1

Powiedziałbym, że jest to prawie tak czyste, jak to tylko możliwe, więc nie ma potrzeby "refaktoryzacji" tutaj. – fresskoma

Odpowiedz

5

Byłoby interesujące, aby przeczytać o innych sytuacjach (znalezienie wszystkich i tylko ostatni minimalny element).

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

Czy jest jakaś znacząca różnica między: ary.each.with_index ... a ary.each_with_index ...? Stwierdziłem, że each_with_index nie dokumentuje. Ale ary.methods.grep (/ each_with_index /); jest prawdziwy. – kyrylo

+1

Oboje są udokumentowane w [Enumerator] (http://rubydoc.info/stdlib/core/1.9.2/Enumerator), z której dziedziczy się Array. "each.with_index" pobiera tablicę i dodaje do niej indeks tworząc tablicę tablic, z wewnętrznymi tablicami zawierającymi oryginalne elementy oraz indeksy. Następnie możesz przekazać to innym transformatorom, takim jak 'map'. 'each_with_index' chce iterować po tablicach tablic. To subtelna różnica, ale nie chciałem pętli "each", chciałem ją przekształcić. –

+0

Ten algorytm będzie wyjątkowo niski. – texasbruce

7

ten przemierza tablicę tylko raz podczas ary.index(ary.min) będzie przemierzać ją dwukrotnie:

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

'ary.index (ary.min)' jest o wiele łatwiejsze do odczytania. – kyrylo

33

Wierzę, że to będzie przemierzać tablicę tylko raz i nadal jest czytelny:

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

Schludne rozwiązanie. Niestety 'Array # last' czyni go brzydkim (' ary.each_with_index.min.last'). – kyrylo

3

Tak naprawdę podoba mi się odpowiedź @andersonvoma, wystarczy tylko raz zapętlić tablicę i nadal pobierać indeks.

A w przypadku, gdy nie chcesz używać ary.each_with_index.min, o to co można zrobić:

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 
Powiązane problemy