2014-09-22 44 views
2

我有一個類似的對象數組,其屬性值爲a,其值可以是bc。該數組可以視爲行的集合,其中數組中的每對項表示一行。我剛剛上市的屬性a的數值爲簡單起見, 例子:Ruby數組迭代和變異

array = [c, b, b, c, c, c, b] 
# array[0], array[1] is one row (c, b) 
# array[2], array[3] is another (b, c) 
# ... 

不能有任何的只是(b, b)行,如果是這樣的話,則b值中的一個必須被交換爲數組中最接近的c值。如果沒有更多c值,則只要b值保留在數組末尾,數組就會有效。

最後陣列的行可以只包含一個值,即(b,)。

例子:

array = [b, c, b, b, c, b, b, b, c, b, b, c, c] 
# becomes 
array = [b, c, b, c, b, b, b, b, c, b, b, c, c] 
array = [b, c, b, c, b, c, b, b, b, b, b, c, c] 
array = [b, c, b, c, b, c, b, c, b, b, b, b, c] 
array = [b, c, b, c, b, c, b, c, b, c, b, b, b] 
# rows: (b, c), (b, c), (b, c), (b, c), (b, c), (b, b,), (b,)  

這是我想到了,我真的不喜歡(因爲它是非常必要和詳細)解決方案

while true do 
    cand = nil 
    array.each_slice(2) do |item, nxt| 
    return if nxt.nil? 
    # pseudo-code: assume b? returns true for a == b   
    next unless item.b? && nxt.b? 
    cand = nxt 
    break 
    end 
    swap_cand = array.slice(array.index(cand), array.length).reject{ |item| item.popular? }.first 
    return if swap_cand.nil? 
    old_index, new_index = array.index(cand), array.index(swap_cand) 
    array[old_index], array[new_index] = array[new_index], array[old_index] 
end 

我一直運行到的一個問題在迭代時我無法改變數組,因此需要兩個循環。

編輯根據@ 7stud的建議清理了一些break語句。

+0

'回做= true如果nxt.nil?'咦?你知道LocalJumpError是什麼嗎?如果你發佈的代碼實際上在def中,那麼設置done = true會爲你做什麼?當你從def返回時,沒有更多的循環 - 沒有更多的東西。 – 7stud 2014-09-22 19:15:28

+0

我認爲這會簡單地設置'done'變量並隨後退出'each_slice'循環。這確實在一個函數定義中,並且如'until'循環所指定,當'done'爲'true'時,這個外部循環退出。 – nicohvi 2014-09-22 19:21:03

+0

**我一直遇到的一個問題是,我無法在迭代它時對數組進行變異**。 'results = []; temp = []; arr.each do | obj |結果<< obj#或temp << obj。根據需要使用盡可能多的數組,並在每個循環中在它們之間來回拖放事物。 – 7stud 2014-09-22 19:22:31

回答

0

可枚舉的#chunk非常適合這個問題。

代碼

def valid?(arr, b) 
    arr.chunk { |e| e } 
    .map(&:last)[0..-2] 
    .select { |e| e.first == b } 
    .max_by(&:size) 
    .size <= 2 
end 

b = 0 
c = 1 
valid?([c, b, b, c, b, b, b], b) #=> true 
valid?([c, b, b, b, c, c, b], b) #=> false 

說明

b = 0 
c = 1 
arr = [c, b, b, c, b, b, b] 
    #=> [1, 0, 0, 1, 0, 0, 0] 
enum = arr.chunk { |e| e } 
    #=> #<Enumerator: #<Enumerator::Generator:0x0000010205aa70>:each> 
enum.to_a # Let's examine the elements of `enum` 
    #=> [[1, [1]], [0, [0, 0]], [1, [1]], [0, [0, 0, 0]]] 
a = enum.map(&:last) 
    #=> [[1], [0, 0], [1], [0, 0, 0]] 
d = a[0..-2] # disregard last value, which may or may not be an array of `b`'s 
    #=> [[1], [0, 0], [1]] 
e = d.select { |e| e.first == b } 
    #=> [[0, 0]] 
f = e.max_by(&:size) 
    #=> [0, 0] 
g = f.size 
    #=> 2 
g <= 2 
    #=> true 
+0

感謝分享,您是否介意解釋此方法如何交換值並轉換數組? – nicohvi 2014-09-22 19:31:49

+0

我將這個問題解釋爲僅僅是爲了確定數組是否「有效」,而沒有參考任何交換。那是對的嗎?順便說一句,當你離開你的評論時,我正在準備解釋。 – 2014-09-22 19:40:32

+0

很抱歉,如果不清楚!這是來自於這個問題(猜測它有點隱藏)'如果在一行中出現三個b值,則需要將其中一個b值交換爲最接近的c值,以便數組遵守規則,如果存在的話。' – nicohvi 2014-09-22 19:41:04