我正在使用一系列midi音高,看起来像这样......
pitches = [
60, nil, nil, nil, 67, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil
]
在这种情况下,指数1,2和3的音高仍为60。
在指数4之后,音高仍然是67。
如何编写方法来识别先前的非零值?
我目前认为这样做的唯一方法看起来有点笨拙:
def pitch_at_step(pitches,step)
if pitches.any?
x = pitches[step]
until x != nil
index -= 1
x = pitches[step]
end
x
else
nil
end
end
预期输出格式为:
pitch_at_step(pitches, 0) # 60
pitch_at_step(pitches, 2) # 60
pitch_at_step(pitches, 4) # 67
pitch_at_step(pitches, 8) # 67
这是最好的解决方案吗?是否有更整洁和/或更有效的方式?
答案 0 :(得分:4)
如果数组不大,你可以使用这样的东西:
pitches[0..index].compact.last
这看起来更整洁,但它不如大数据阵列那么好
答案 1 :(得分:3)
pitches.slice_before(&:itself).flat_map{|a| a.fill(a.first)}
# => [60, 60, 60, 60, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
# 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67]
答案 2 :(得分:2)
这是构建转换数组的简单方法:
last = pitches.first
pitches[1..-1].map { |i| curr = i || last; last = curr; curr }
.unshift(pitches.first)
#=> [60, 60, 60, 60, 67,... 67]
OP没有说明pitches
的第一个元素是否总是非零。假设:
pitches = [nil, nil, 61, nil, nil, 60, nil]
上述方法将返回:
[nil, nil, 61, 61, 61, 60, 60]
这就是我们想要的。对于所有pitches[step] = nil
pitches[i] = nil
(i < step
是step
的给定元素的索引)pitches
和{{1}}时,其他一些答案会发生绊倒。
答案 3 :(得分:2)
如果您要使用大多数nil
的大型数组,为什么不使用哈希值,只存储非零值?你看着钥匙。 (这里是未经优化的版本)
pitches = {0 => 60, 4 => 67}
def find(idx)
lower = pitches.keys.select { |i| i <= idx}
return pitches[lower.sort.last]
end
如果性能有问题,您可以跟踪排序的密钥。
答案 4 :(得分:1)
获得一个值:
value = index.downto(0){|i| pitches[i] and break pitches[i] }
计算所有值:
values = (y = nil) || pitches.map{|x| x ? y = x : y }
答案 5 :(得分:1)
这也可以通过Enumerable#chunk
:
tmp = nil
pitches.chunk {|el| tmp = el unless el.nil?; tmp }.
map {|val, ar| [val] * ar.size }.flatten
# => [60, 60, 60, 60, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
# 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67]
答案 6 :(得分:0)
我认为这是在Ruby中实现它的好方法:
pitches[0..index].reverse_each.find{|x|x}