给出一个包含数字的数组,请遵循以下规则:
0
删除所有先前的数字和所有后续的相邻偶数。1
删除所有先前的数字和所有随后的相邻奇数。1
,则可以将其删除我正在尝试编写一种减少数组的算法,但我只能提出一个不好看的解决方案:
def compress(array)
zero_or_one_index = array.rindex { |element| [0,1].include? element }
array.slice!(0, zero_or_one_index) if zero_or_one_index
deleting = true
while deleting
deleting = false
array.each_with_index do |element, index|
next if index.zero?
previous_element = array[index - 1]
if (previous_element == 0 && element.even?) ||
(previous_element == 1 && element.odd?)
array.delete_at(index)
deleting = true
break
end
end
end
array.shift if array[0] == 1
end
问题是delete_if
和类似的东西开始弄乱结果,如果我在数组上进行迭代时删除了元素,则不得不使用while循环。
示例:
compress([3, 2, 0]) #=> [0]
compress([2, 0, 4, 6, 7]) #=> [0,7]
compress([2, 0, 4, 1, 3, 6]) #=> [6]
compress([3, 2, 0, 4, 1, 3, 6, 8, 5]) #=> [6,8,5]
这个问题是在我对cancancan进行一些重构以优化规则定义的情况下出现的。
答案 0 :(得分:3)
这是我要解决的问题:
def compress(arr)
return arr unless idx = arr.rindex {|e| e == 0 || e == 1}
value = arr[idx]
method_options = [:even?,:odd?]
arr[idx..-1].drop_while do |n|
n.public_send(method_options[value])
end.tap {|a| a.unshift(value) if value.zero? }
end
首先,我们使用Array#rindex
查找最后出现的0或1的索引。如果没有,则返回Array
。
然后我们获得该索引处的值。
然后我们使用Array#[]
从索引处切下Array
的尾端。
然后使用:even?
删除与:odd?
(value
或0
)对应的所有连续相邻1
或Array#drop_while
号。
最后,如果value
是0
,我们将其放回Array
的前面,然后再返回。
示例
compress([3, 2, 0])
#=> [0]
compress([2, 0, 4, 6, 7])
#=> [0,7]
compress([2, 0, 4, 1, 3, 6])
#=> [6]
compress([3, 2, 0, 4, 1, 3, 6, 8, 5])
#=> [6,8,5]
compress([4, 5, 6])
#=> [4,5,6]
compress([0])
#=> [0]
compress([1])
#=> []
如果您的目标是转变,正如您的问题和要点所暗示的那样,老实说,我不会改变我所拥有的,而是去做:
def compress!(arr)
arr.replace(compress(arr))
end
例如
a = [3, 2, 0, 4, 1, 3, 6, 8, 5]
a == compress!(a)
#=> true
a
#=> [6,8,5]