我有一组类似的对象,其属性a
可以包含值b
或c
。可以将该数组视为行的集合,其中数组中的每对项表示一行。为简单起见,我刚刚列出了属性a
的值,
例如:
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 :(得分:0)
Enumerable#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