Bardziej ciekawa składnia niż problem do rozwiązania ...
Mam dwie tablice o równej długości i chcę wykonać iterację po obu naraz - na przykład wypisać obie ich wartości w określonym indeksie.
@budget = [ 100, 150, 25, 105 ]
@actual = [ 120, 100, 50, 100 ]
Wiem, że mogę używać each_index
i indeksować tablice w następujący sposób:
@budget.each_index do |i|
puts @budget[i]
puts @actual[i]
end
Czy istnieje sposób w Rubim, aby to zrobić lepiej? Coś takiego ?
# Obviously doesn't achieve what I want it to - but is there something like this?
[@budget, @actual].each do |budget, actual|
puts budget
puts actual
end
Odpowiedzi:
>> @budget = [ 100, 150, 25, 105 ] => [100, 150, 25, 105] >> @actual = [ 120, 100, 50, 100 ] => [120, 100, 50, 100] >> @budget.zip @actual => [[100, 120], [150, 100], [25, 50], [105, 100]] >> @budget.zip(@actual).each do |budget, actual| ?> puts budget >> puts actual >> end 100 120 150 100 25 50 105 100 => [[100, 120], [150, 100], [25, 50], [105, 100]]
źródło
Użyj tej
Array.zip
metody i przekaż jej blok, aby kolejno iterować po odpowiednich elementach.źródło
Istnieje inny sposób iteracji po dwóch tablicach naraz przy użyciu modułów wyliczających:
2.1.2 :003 > enum = [1,2,4].each => #<Enumerator: [1, 2, 4]:each> 2.1.2 :004 > enum2 = [5,6,7].each => #<Enumerator: [5, 6, 7]:each> 2.1.2 :005 > loop do 2.1.2 :006 > a1,a2=enum.next,enum2.next 2.1.2 :007?> puts "array 1 #{a1} array 2 #{a2}" 2.1.2 :008?> end array 1 1 array 2 5 array 1 2 array 2 6 array 1 4 array 2 7
Enumeratory są potężniejsze niż przykłady użyte powyżej, ponieważ pozwalają między innymi na nieskończone serie i równoległe iteracje.
źródło
loop
pokazanego powyżej?Oprócz tego,
a.zip(b).each{|x,y| }
jak powiedzieli inni, możesz również powiedzieć[a,b].transpose.each{|x,y| }
, co wydaje mi się nieco bardziej symetryczne. Prawdopodobnie nie tak szybko, ponieważ tworzysz dodatkową[a,b]
tablicę.źródło
transpose
jest to, że wywołuje wyjątek, jeśli dwie tablice nie są tej samej długości.W odniesieniu do pierwotnego pytania, do iteracji po tablicach o nierównej długości, w których chcesz, aby wartości były cykliczne, możesz użyć
[1,2,3,4,5,6].zip([7,8,9].cycle)
a Ruby ci to da
[[1, 7], [2, 8], [3, 9], [4, 7], [5, 8], [6, 9]]
Oszczędza to
nil
wartości, które uzyskasz po samym użyciu zipźródło
Po prostu spakowanie dwóch tablic razem działa dobrze, jeśli masz do czynienia z tablicami. Ale co, jeśli masz do czynienia z niekończącymi się wyliczającymi, takimi jak coś takiego:
enum1 = (1..5).cycle enum2 = (10..12).cycle
enum1.zip(enum2)
zawodzi, ponieważzip
próbuje ocenić wszystkie elementy i połączyć je. Zamiast tego zrób to:To
lazy
oszczędza, sprawiając, że wynikowy moduł wyliczający jest leniwy.źródło
A co z kompromitacją i używaniem #each_with_index?
include Enumerable @budget = [ 100, 150, 25, 105 ] @actual = [ 120, 100, 50, 100 ] @budget.each_with_index { |val, i| puts val; puts @actual[i] }
źródło