有一个对象数组,其中许多对象多次出现在数组中。有一个项目的特定位置的索引。我想在保留索引的同时从所有位置的数组中删除一个对象。已删除项目的索引应移至下一个可用项目,如果没有,则应将其回绕到数组的开头。
我不认为我能很好地解释它,所以这是一个简单的例子:
array = [:b, :a, :b]
index = 2
现在从数组中删除:a
,索引现在应为1,因为第二个:b
现在位于索引1。
假设索引指向已删除的对象,它应该移动到下一个可用对象。因此,如果索引为1,则它不会改变,因为它现在指向紧随:b
的{{1}}。
这是一个环绕的例子:
:a
如果删除array = [:b, :a]
index = 1
,则索引应该回滚到下一个可用索引,或者为0。
看起来很简单,但边缘情况要复杂得多。这是我能想到的最复杂的例子:
:a
删除':a'后,生成的数组为array = [:a, :a, :b, :a, :c, :b, :a]
。从所有可能的起始索引(0到6),它们应该更改为0,0,0,1,1,2,0。
假设数组中有多个对象,因此删除后它永远不会变空。
(编辑)
感谢@Raffael通知我,我应该包括我迄今为止尝试过的内容。这是我的第一次尝试:
[:b, :c, :b]
是数组。@items
是需要调整的索引。@current_item_index
是要删除的项目。代码:
item
它似乎并非如此" Ruby" (不清楚也不简洁)。同样不具备高效性,因为它在列表中运行两次 - 更不用说所有那些不会很好的indexes = @items.each_index.each_with_object([]) do |i, memo|
memo << i if @items[i] == item
end
indexes.reverse.each do |i|
@items.delete_at(i)
@current_item_index -= 1 if i < @current_item_index
@current_item_index = 0 unless @current_item_index < @items.size
end
次呼叫。
答案 0 :(得分:1)
新索引等于旧数组中
的元素数您可以在构建新数组时随时计算这些数据,如下所示:
def delete_and_follow(old_array, old_index, unwanted)
new_array, new_index = [], 0
old_array.each.with_index do |item, idx|
unless item == unwanted
new_array << item
new_index += 1 if idx < old_index
end
end
new_index = 0 if new_index >= new_array.length
[new_array, new_index]
end
或者用更少的代码做同样的事情(虽然有点神秘):
def delete_and_follow(old_array, old_index, unwanted)
new_index = old_array.take(old_index).count{ |item| item != unwanted }
new_array = old_array - [unwanted]
[new_array, new_index % new_array.length]
end
HTH!