2014-09-22 48 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