Jak znaleźć średnią z tablicy?
Jeśli mam tablicę:
[0,4,8,2,5,0,2,6]
Uśrednianie dałoby mi 3,375.
ruby-on-rails
ruby
rozsiany
źródło
źródło
Odpowiedzi:
Spróbuj tego:
Zwróć uwagę na to
.to_f
, co chcesz uniknąć problemów z dzieleniem liczb całkowitych. Możesz także:Możesz zdefiniować go jako część,
Array
jak sugerował inny komentator, ale musisz unikać dzielenia liczb całkowitych, w przeciwnym razie wyniki będą błędne. Ponadto nie ma to ogólnie zastosowania do każdego możliwego typu elementu (oczywiście średnia ma sens tylko dla rzeczy, które można uśrednić). Ale jeśli chcesz wybrać tę trasę, skorzystaj z tego:Jeśli jeszcze tego nie widziałeś
inject
, nie jest to tak magiczne, jak mogłoby się wydawać. Iteruje po każdym elemencie, a następnie stosuje do niego wartość akumulatora. Akumulator jest następnie przekazywany do następnego elementu. W tym przypadku nasz akumulator jest po prostu liczbą całkowitą, która odzwierciedla sumę wszystkich poprzednich elementów.Edycja: Komentator Dave Ray zaproponował miłą poprawę.
Edycja: Używanie propozycji komentatora Glenna Jackmana
arr.inject(:+).to_f
jest również miłe, ale może zbyt sprytne, jeśli nie wiesz, co się dzieje. To:+
jest symbol; przekazany do wtrysku, stosuje metodę nazwaną przez symbol (w tym przypadku operację dodawania) do każdego elementu w stosunku do wartości akumulatora.źródło
arr.inject(0.0) { |sum,el| sum + el } / arr.size
.inject
interfejsu, o której mowa w dokumentacji.to_proc
Operator&
.Array#inject
tutaj jest przesada. Po prostu użyj#sum
. Np.arr.sum.to_f / arr.size
Wersja tego, która nie używa
instance_eval
, to:źródło
instance_eval
pozwala uruchomić kod, określając tylkoa
jeden raz, dzięki czemu można go połączyć z innymi poleceniami. Tj.random_average = Array.new(10) { rand(10) }.instance_eval { reduce(:+) / size.to_f }
Zamiastrandom = Array.new(10) { rand(10) }; random_average = random.reduce(:+) / random.size
self
wewnątrz tego bloku, możesz napotkać problemy.)instance_eval
To więcej w przypadku metaprogramowania lub DSL.Uważam, że najprostsza odpowiedź brzmi
źródło
reduce
jest to metodaEnumerable
miksu używana przezArray
. I pomimo jego nazwy, zgadzam się z @ShuWu ... chyba że używasz Railsów, które implementująsum
.Miałem nadzieję, że Math. Średnia (wartości), ale bez takiego szczęścia.
źródło
sum
metodę, więc wydaje się, że jest to poprawna odpowiedź po 6 latach, godna nagrody Nostradamus.Wersje Ruby> = 2.4 mają metodę Enumerable # sum .
Aby uzyskać średnią zmiennoprzecinkową, możesz użyć liczby całkowitej # fdiv
W przypadku starszych wersji:
źródło
Niektóre testy porównawcze najlepszych rozwiązań (w kolejności najbardziej wydajnych):
Duża tablica:
Małe tablice:
źródło
źródło
nil
zamiast 0?Pozwól, że przyniosę coś do rywalizacji, która rozwiązuje problem dzielenia przez zero:
Muszę jednak przyznać, że „try” to pomocnik Railsów. Ale możesz to łatwo rozwiązać:
BTW: Myślę, że to prawda, że średnia pustej listy wynosi zero. Średnia niczego to nic, a nie 0. To jest oczekiwane zachowanie. Jeśli jednak zmienisz na:
wynik dla pustych tablic nie będzie wyjątkiem, jak się spodziewałem, ale zwraca NaN ... Nigdy wcześniej tego nie widziałem w Ruby. ;-) Wydaje się, że jest to szczególne zachowanie klasy Float ...
źródło
czego nie lubię w zaakceptowanym rozwiązaniu
jest to, że tak naprawdę nie działa w czysto funkcjonalny sposób. potrzebujemy zmiennej arr do obliczenia arr.size na końcu.
aby rozwiązać to czysto funkcjonalnie, musimy śledzić dwie wartości: sumę wszystkich elementów i liczbę elementów.
Santhosh ulepszył to rozwiązanie: zamiast argumentu r będącego tablicą, moglibyśmy użyć destrukcji, aby natychmiast rozdzielić ją na dwie zmienne
jeśli chcesz zobaczyć, jak to działa, dodaj kilka putów:
Możemy również użyć struktury zamiast tablicy do przechowywania sumy i liczby, ale najpierw musimy zadeklarować strukturę:
źródło
end.method
użyłem rubinu, dzięki za to!arr.inject([0.0,0]) { |(sum, size), el| [ sum + el, size + 1 ] }.inject(:/)
Dla rozrywki publicznej jeszcze jedno rozwiązanie:
źródło
Nie mam ruby na tym komputerze, ale coś w tym zakresie powinno działać:
źródło
Dodaj
Array#average
.Często robiłem to samo, więc pomyślałem, że rozsądnie byłoby po prostu rozszerzyć
Array
klasę za pomocą prostejaverage
metody. Nie działa na nic poza tablicą liczb takich jak liczby całkowite, zmiennoprzecinkowe lub dziesiętne, ale jest przydatny, gdy używasz go poprawnie.Korzystam z Ruby on Rails, więc umieściłem go,
config/initializers/array.rb
ale możesz go umieścić w dowolnym miejscu na starcie itp.config/initializers/array.rb
źródło
źródło
Rozwiązuje dzielenie przez zero, dzielenie liczb całkowitych i jest łatwy do odczytania. Można go łatwo zmodyfikować, jeśli wybierzesz opcję zwracania pustej tablicy 0.
Ten wariant też mi się podoba, ale jest trochę bardziej niewygodny.
źródło
źródło
Ta metoda może być pomocna.
źródło
Bez konieczności powtarzania tablicy (np. Idealne dla jedno-liniowych):
źródło
Krótka, ale przy użyciu zmiennej instancji
źródło
a_size = nil; [1,2].tap { |a| a_size = a.size }.inject(:+).to_f/a_size
tworzyć zmienną instancji.Możesz spróbować czegoś takiego:
źródło