2015-04-03 130 views
3

什麼是寫這段代碼的慣用Ruby方式?迭代數組中的每個元素(第一個元素除外)

給定一個數組,我想遍歷該數組的每個元素,但跳過第一個元素。我想在不分配新數組的情況下執行此操作。

以下是我提出的兩種方法,但都不覺得特別優雅。

這工作,但似乎太冗長:

arr.each_with_index do |elem, i| 
    next if i.zero? # skip the first 
    ... 
end 

這工作,但分配一個新的數組:

arr[1..-1].each { ... } 

編輯/澄清:我想避免分配第二陣列。最初我說我想避免「複製」陣列,這是令人困惑的。

+1

你的第二個不會使數組的副本。 – sawa 2015-04-03 01:38:09

+2

@sawa它不會複製數組本身,但它會創建一個新的數組,除了第一個元素外,每個'Array#[]'上的文檔都會被創建。我誤解了這個要求嗎? – 2015-04-03 02:41:21

+0

我同意你的評估。其他兩個選項僅使用索引:'(1 ... arr.size).each {| i | .... ref arr [i] ...}'或一個標誌:'first = true; arr.each {| e |如果第一個; first = false;下一個;結束; ''。 – 2015-04-03 03:05:57

回答

5

使用內部枚舉肯定是更直觀,你可以做到這一點相當優雅,像這樣:

class Array 
    def each_after(n) 
    each_with_index do |elem, i| 
     yield elem if i >= n 
    end 
    end 
end 

現在:

arr.each_after(1) do |elem| 
    ... 
end 
+0

迄今爲止最好的解決方案 – 2015-04-03 04:53:34

+0

我同意。或者,'each_after'方法可以在'Enumerable'而不是'Array'上定義,並且具有相同的效果,對吧?似乎它對於非數組枚舉器也很有用。 – 2015-04-03 04:56:55

+0

非常好!還有@ MattBrictson的建議,如果沒有給出塊,考慮返回一個枚舉器,以允許鏈接。 – 2015-04-03 08:29:26

1

我想在不創建數組副本的情況下執行此操作。

1)內部迭代器:

arr = [1, 2, 3] 
start_index = 1 

(start_index...arr.size).each do |i| 
    puts arr[i] 
end 

--output:-- 
2 
3 

2)外部迭代器:

arr = [1, 2, 3] 
e = arr.each 
e.next 

loop do 
    puts e.next 
end 

--output:-- 
2 
3 
+0

謝謝!從概念上講,這正是我想到的。即:枚舉數組,放棄第一個元素,然後處理其餘的元素。但代碼很羅嗦。我想這是不可避免的? – 2015-04-03 03:33:25

+0

關於#2,應該注意的是,通過消除塊,你已經擴大了以前在OP的塊中的範圍。 – 2015-04-03 03:44:56

0

好吧,也許這是不好的形式來回答我的問題。但我已經費盡我對這個大腦和鑽研的Enumerable文檔,我想我已經找到了一個很好的解決方案:

arr.lazy.drop(1).each { ... } 

這裏的證明,它的作品:-)

>> [1,2,3].lazy.drop(1).each { |e| puts e } 
2 
3 

簡潔:是的。習語Ruby ......也許?你怎麼看?

+2

'drop'仍然會創建一個新的數組,'lazy'只會延遲這個活動,直到調用'each'。不錯,儘管。 – PinnyM 2015-04-03 04:34:52

+0

謝謝@PinnyM。接得好! – 2015-04-03 04:37:41

相關問題