2014-09-22 6 views
2

У меня есть массив похожих объектов с атрибутом a, который может иметь значения b или c. Массив можно рассматривать как набор строк, где каждая пара элементов массива представляет одну строку. Я только что перечислил значение атрибута 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 не останутся в конце массива.

final строка массива может состоять только из одна значение, i. е. (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.

+0

'возвращение сделано = верно, если nxt.nil?' А? Вы знаете, что такое LocalJumpError? Если код, который вы опубликовали, действительно находится внутри def, то что делает сделанная установка = true для вас? Когда вы возвращаетесь из def, больше нет цикла - больше ничего. – 7stud

+0

Я предположил, что это просто установит переменную 'done' и впоследствии выйдет из цикла' each_slice'. Это действительно внутри определения функции, и, как указано циклом 'until', этот внешний цикл завершается, когда' done' является 'true'. – nicohvi

+0

** Проблема, с которой я столкнулась, заключалась в том, что я не мог мутировать массив, итерации по ней **. 'results = []; temp = []; arr.each do | obj | результаты << obj #or temp << obj. Используйте столько массивов, сколько вам нужно, и перемешайте вещи между ними в каждом цикле. – 7stud

ответ

0

Перечисляемый # кусок хорошо подходит для этой проблемы.

Код

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

+0

Я интерпретировал этот вопрос как просто для того, чтобы определить, является ли массив «действительным», без ссылки на любую замену. Это верно? Кстати, я готовил объяснение, когда вы оставили свой комментарий. –

+0

Извините, если неясно! Это из вопроса (предположим, что это было скрыто). Если в строке есть три значения b, одно из значений b должно быть заменено для ближайшего значения c, чтобы массив мог придерживаться правила, если таковые существуют. – nicohvi

Смежные вопросы