2013-08-13 15 views
8

W języku Ruby jest zły sposób na użycie pętli for. Jest to powszechnie zrozumiałe. Przewodnik styl polecił mi: (https://github.com/bbatsov/ruby-style-guide#source-code-layout) mówi:Jak zamienić pętlę for w języku Ruby?

„Nigdy nie używać do, chyba że wiesz dokładnie, dlaczego Większość iteratorów czasowych powinny być stosowane zamiast tego jest realizowany w warunkach każdy (tak.. dodajesz poziom dwukierunkowości), ale z niespodzianką - bo nie wprowadza nowego zakresu (w przeciwieństwie do każdego), a zmienne zdefiniowane w jego bloku będą widoczne poza nim. "

podanym przykładzie jest:

arr = [1, 2, 3] 

#bad 
for elem in arr do 
    puts elem 
end 

# good 
arr.each { |elem| puts elem } 

ja zbadali i nie mogę znaleźć wyjaśnienie, w jaki sposób symulować pętli for, które stanowi wartość iteracji mogę przechodzić do miejsc lub wykonywać działania arytmetyczne na . Na przykład, co by wymienić:

for i in 0...size do 
    puts array1[i] 
    puts array2[size-1 - i] 
    puts i % 2 
end 

To łatwe, jeśli jest to jedna tablica, ale często potrzebują aktualnej pozycji do innych celów. Jest albo proste rozwiązanie, którego mi brakuje, albo sytuacje, w których wymagane jest dla. Dodatkowo słyszę, jak ludzie mówią o dla, jakby nigdy nie było potrzebne. Jakie są zatem ich rozwiązania?

Czy można to poprawić? A jakie jest rozwiązanie, jeśli takie istnieje? Dzięki.

Odpowiedz

10

Jeśli chcesz iteracyjne nad zbiór i śledzić indeksu, należy each_with_index:

fields = ["name", "age", "height"] 

fields.each_with_index do |field,i| 
    puts "#{i}. #{field}" # 0. name, 1. age, 2. height 
end 

Twój for i in 0...size przykład postać:

array1.each_with_index do |item, i| 
    puts item 
    puts array2[size-1 - i] 
    puts i % 2 
end 
+0

Zakładając, że 'tablica1' i' tablica2' mają ten sam rozmiar, najlepiej napisać to jako 'tablica2 [-1 - i]', aby uniknąć konieczności obliczania "rozmiaru". – Borodin

3

Nie zapomnij można zrobić również takie fajne rzeczy:

fields = ["name", "age", "height"] 

def output name, idx 
    puts "#{idx}. #{name}" 
end 

fields.each_with_index &method(:output) 

Wyjście

0. name 
1. age 
2. height 

można wykorzystywać tę technikę jako klasy lub instancji metody zbyt

class Printer 
    def self.output data 
    puts "raw: #{data}" 
    end 
end 

class Kanon < Printer 
    def initialize prefix 
    @prefix = prefix 
    end 
    def output data 
    puts "#{@prefix}: #{data}" 
    end 
end 

def print printer, data 
    # separating the block from `each` allows 
    # you to do interesting things 
    data.each &printer.method(:output) 
end 

metoda przykład przy użyciu klasy

print Printer, ["a", "b", "c"] 
# raw: a 
# raw: b 
# raw: c 

metoda przykład za pomocą instancji

kanon = Kanon.new "kanon prints pretty" 
print kanon, ["a", "b", "c"] 
# kanon prints pretty: a 
# kanon prints pretty: b 
# kanon prints pretty: c 
+0

Można, ale dlaczego miałbyś? Co to naprawdę dodaje? – meagar

+0

Oddziela blok od iteracji "each *". Oznacza to, że możesz trzymać blok w dowolnym miejscu; może to być metoda klasy lub instancji, może to być dynamiczny proces, itp. Wystarczy wykazać pewną elastyczność widząc, że OP wydaje się być względnie zielony. Otrzymawszy już +2, nie sądzę, żebym był jedyny, który uzna to za przydatne. – naomik

+0

Zgadzam się, że jest to przydatne, ale nie jest to istotne ani na temat. Nie jest to przydatne w sytuacji opisywanej przez to pytanie. – meagar

Powiązane problemy