Mam tablicę liczb całkowitych.
Na przykład:
array = [123,321,12389]
Czy jest jakiś dobry sposób, aby uzyskać ich sumę?
Wiem to
sum = 0
array.each { |a| sum+=a }
pracowałbym.
Mam tablicę liczb całkowitych.
Na przykład:
array = [123,321,12389]
Czy jest jakiś dobry sposób, aby uzyskać ich sumę?
Wiem to
sum = 0
array.each { |a| sum+=a }
pracowałbym.
Odpowiedzi:
Spróbuj tego:
array.inject(0){|sum,x| sum + x }
Zobacz wyliczalną dokumentację Ruby
(uwaga: 0
potrzebna jest skrzynka podstawowa, aby 0
zamiast niej została zwrócona pusta tablica nil
)
array.inject(:+)
jest bardziej wydajny.
array.inject(:+)
wydaje się powodować problemy w wyjątkach Ruby 1.8.6 „LocalJumpError: nie podano żadnego bloku” może się pojawić.
array.sum
może dać ci sumę wartości tablicy.
reduce
, który jest aliasem inject
(jak w array.reduce( :+ )
).
inject
zamiast reduce
.
Lub wypróbuj sposób Ruby 1.9:
array.inject(0, :+)
Uwaga: 0
skrzynka podstawowa jest potrzebna, w przeciwnym razie nil
zostaną zwrócone w pustych tablicach:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
jest nieco bezpieczniejszy. Zapewnia to, że jeśli masz pustą listę, dostajesz 0 zamiast zera .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Choć odpowiednik array.inject(0, :+)
terminu „ redukuj” wchodzi w bardziej popularne języki wraz ze wzrostem modeli programowania MapReduce .
wstrzykiwanie , zmniejszanie , składanie , gromadzenie i kompresja są synonimami jako klasa funkcji składania . Najważniejsza jest spójność w całej bazie kodu, ale ponieważ różne społeczności wolą jedno słowo od drugiego, warto jednak znać alternatywy.
Aby podkreślić znaczenie ograniczania mapy, oto wersja, która jest nieco bardziej wyrozumiała dla tego, co kończy się w tej tablicy.
array.map(&:to_i).reduce(0, :+)
Kilka dodatkowych istotnych lektur:
reduce
mówi mi więcej o tym, co robi ta funkcja, ale inject
brzmi znacznie lepiej .
reduce
i map
tak funkcje wyższego rzędu poprzedzają MapReduce. Inspiracja działa w drugą stronę. W sensie MapReduce jest to nieco inna operacja niż zwykła redukcja funkcjonalna, mająca implikacje dla sposobu komunikowania się różnych maszyn.
Alternatywnie (tylko dla porównania), jeśli masz zainstalowane Railsy (właściwie tylko ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
lub wymagają wszystkie aktywnego wsparcia: require 'active_support/all'
. Więcej informacji na ten temat tutaj: Dokumenty API
activesupport
jest masywny zależność do przeciągania do projektu, aby przejść od array.inject(:+)
do array.sum
.
require 'active_support/core_ext/enumerable'
bez .rb
przyrostka, ponieważ jest to dodawane domyślnie.
Dla Ruby> = 2.4.0 możesz używać sum
z Enumerables.
[1, 2, 3, 4].sum
Klasy podstawowe typu mokeypatch są niebezpieczne. Jeśli lubisz niebezpieczeństwo i używasz starszej wersji Ruby, możesz dodać #sum
do Array
klasy:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Możesz użyć trafnie nazwanej metody Enumerable#sum
. Ma wiele zalet, inject(:+)
ale na końcu jest też kilka ważnych uwag.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Ta metoda nie jest równoważna z #inject(:+)
. Na przykład
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
Również,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
Zobacz tę odpowiedź, aby uzyskać więcej informacji o tym, dlaczego sum
tak jest.
Ze względu na różnorodność możesz to zrobić, jeśli tablica nie jest tablicą liczb, ale tablicą obiektów, które mają właściwości, które są liczbami (np. Ilość):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. Zobacz inne odpowiedzi.
map
wtedy inject
wymaga dwukrotnego przejścia przez tablicę: raz, aby utworzyć nową tablicę, drugi, aby zsumować członków. Ta metoda jest nieco bardziej szczegółowa, ale także bardziej wydajna.
Ruby 2.4+ / Rails - array.sum
tj[1, 2, 3].sum # => 6
Ruby przed 2.4 - array.inject(:+)
lubarray.reduce(:+)
* Uwaga: #sum
Metoda jest nowym dodatkiem do 2.4, enumerable
dzięki czemu będziesz mógł używać array.sum
czystego rubinu, nie tylko Railsów.
Ruby 1.8.7 to:
array.inject(0, &:+)
Możesz po prostu użyć:
example = [1,2,3]
example.inject(:+)
inject(:+)
ale to nie działa inject :+
?
Wystarczy
[1,2,3].inject('+')
Ruby 2.4.0 zostało wydane i ma metodę Enumerable # sum . Więc możesz to zrobić
array.sum
Przykłady z dokumentów:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
Pozwala również na [1,2].sum{|x| x * 2 } == 6
:
# http://madeofcode.com/posts/74-ruby-core-extension-array-sum
class Array
def sum(method = nil, &block)
if block_given?
raise ArgumentError, "You cannot pass a block and a method!" if method
inject(0) { |sum, i| sum + yield(i) }
elsif method
inject(0) { |sum, i| sum + i.send(method) }
else
inject(0) { |sum, i| sum + i }
end
end
end
dla tablicy z zerowymi wartościami możemy wykonać kompaktowanie, a następnie wstrzyknąć sumę ex-
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
Metoda 1:
[1] pry(main)> [1,2,3,4].sum
=> 10
[2] pry(main)> [].sum
=> 0
[3] pry(main)> [1,2,3,5,nil].sum
TypeError: nil can't be coerced into Integer
Metoda 2:
[24] pry(main)> [].inject(:+)
=> nil
[25] pry(main)> [].inject(0, :+)
=> 0
[4] pry(main)> [1,2,3,4,5].inject(0, :+)
=> 15
[5] pry(main)> [1,2,3,4,nil].inject(0, :+)
TypeError: nil can't be coerced into Integer
from (pry):5:in `+'
Metoda 3:
[6] pry(main)> [1,2,3].reduce(:+)
=> 6
[9] pry(main)> [].reduce(:+)
=> nil
[7] pry(main)> [1,2,nil].reduce(:+)
TypeError: nil can't be coerced into Integer
from (pry):7:in `+'
Metoda 4: Gdy tablica zawiera zero i puste wartości, domyślnie, jeśli użyjesz którejkolwiek z powyższych funkcji zmniejsz, podsumuj, wstrzyknij wszystko przez
TypeError: zero nie może być zmuszone do liczby całkowitej
Możesz to przezwyciężyć,
[16] pry(main)> sum = 0
=> 0
[17] pry(main)> [1,2,3,4,nil, ''].each{|a| sum+= a.to_i }
=> [1, 2, 3, 4, nil, ""]
[18] pry(main)> sum
=> 10
Metoda 6: eval
Ocenia wyrażenie Ruby w ciągu.
[26] pry(main)> a = [1,3,4,5]
=> [1, 3, 4, 5]
[27] pry(main)> eval a.join '+'
=> 13
[30] pry(main)> a = [1,3,4,5, nil]
=> [1, 3, 4, 5, nil]
[31] pry(main)> eval a.join '+'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
1+3+4+5+
To jest najkrótsza droga. Spróbuj.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* To działało dobrze dla mnie jako nowego programisty. Możesz dostosować zakres liczb, zmieniając wartości w []
Możesz to również zrobić w prosty sposób
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Możesz użyć .map i .sum, takich jak:
array.map { |e| e }.sum
array.sum
array.sum