2012-07-04 54 views
1

我有一個對象,treetree有一個屬性,tree.elementstree.elements是一個包含元素和其他可能的子樹的數組,它們將依次擁有自己的elements數組,等等。Ruby中遞歸替換數組

我需要一種方法,如果它們屬於某個類,它將能夠替換樹中的對象。問題是內聯替換元素。

顯然,下面的不會起作用:

[1,2,3].each { |n| n = 1 } 
# => [1,2,3] 

但是,這將:

a = [1,2,3] 
a.each_with_index { |n, idx| a[idx] = 1 } 
# => [1,1,1] 

不過,我使用的是遞歸函數來遍歷,並與內容替換佔位符,如所以:

def replace_placeholders(elements) 
    elements.each do |e| 
     if e.respond_to?(:elements) and e.elements.any? 
      replace_placeholders(e.elements) 
     elsif e.is_a? Placeholder 
      e = "some new content" # << replace it here 
     end 
    end 
end 

保持對指數的追蹤非常複雜。我試過e.replace("some new content"),但這不起作用。什麼是最好的方式去做這件事?

+0

正在取代元素內聯超級本質?沒有它,它變得更容易。 –

+0

@SergioTulentsev不,不是 - 不知道爲什麼我沒有想到這一點。 –

+0

請參閱我的回答然後:) –

回答

3

我將創建一個新的陣列,而不是試圖就地更新。沿着這些線的東西應該工作:

def replace_placeholders(elements) 
    elements.map do |e| 
    if e.respond_to?(:elements) and e.elements.any? 
     e.elements = replace_placeholders(e.elements) # replace array 
     e # return e itself, so that map works correctly. 
    elsif e.is_a? Placeholder 
     "some new content" 
    end 
    end 
end 
+0

感謝,偉大的工作 - 我需要做的一件事,雖然是添加一個else語句並返回e,否則我會放棄元素,但謝謝。 –

1

使用陣列#收集:

[1,2,3].collect { |n| 1 } 
# => [1,1,1] 

,做你想要使用此塊參數什麼的。

所以你的代碼會是這樣的:

elements.collect{ |n| if n.respond_to?(:elements) and n.elements.any? 
     replace_placeholders(n.elements) 
    elsif n.is_a? Placeholder 
     "some new content" # << replace it here 
    end 
}