Ruby 如何从数组中删除范围

Ruby 如何从数组中删除范围,ruby,Ruby,我试图找到与remove\u range(当然不存在)等效的内容,如下所示。似乎没有简单的方法来实现这个功能 a = [0,2,8,2,4,5,] b = a.remove_range(1,2) #remove items between index 1 and 2 ,inclusively #expect b == [0,2,4,5] b = a.remove_range(3,4) #expect b == [0,2,8,5] 在发布解决方案之前,请至少测试以上两种情况:) 假设范围的大小为

我试图找到与
remove\u range
(当然不存在)等效的内容,如下所示。似乎没有简单的方法来实现这个功能

a = [0,2,8,2,4,5,]
b = a.remove_range(1,2) #remove items between index 1 and 2 ,inclusively
#expect b == [0,2,4,5]
b = a.remove_range(3,4)
#expect b == [0,2,8,5]
在发布解决方案之前,请至少测试以上两种情况:)

假设范围的大小为M,此操作需要O(1)空间和O(N-M)时间复杂度

编辑: 我看到人们不断发布
a-a[range]
。但这是不正确的,即删除[range]中存在的元素,而不是删除该元素所属的范围


a-a[1..2]
将返回
[0,4,5]
。但是,我们希望保留第三个元素,即
2

,这是内置在数组类中的。只需减去你不想要的部分:

2.0.0-p353 :001 > ar = [0,2,8,2,4,5]
=> [0, 2, 8, 2, 4, 5] 
2.0.0-p353 :002 > ar - ar[2..3]
=> [0, 4, 5] 
类数组
def移除_范围(sp、ep)
如果sp<0 | | ep>size-1,则引发ArgumentError
切片(0…sp).concat(切片(ep+1..-1))
结束
结束

感谢Cary Swoveland的好建议

您可以使用可枚举模块完成一些很酷的技巧:

a = [0, 2, 8, 2, 4, 5]
r = 1..2
a.reject.with_index { |v, i| r.include?(i) }  # => [0, 2, 4, 5]
请注意,这不会修改原始数组,而是返回一个新数组。您可以使用
拒绝如果要修改数组

class Array
  def remove_range(f,l)
    self[0..f-1].concat(self[l+1..-1])
  end
end

a = [0,2,8,2,4,5]
b = a.remove_range(1,2)
[0, 2, 4, 5]
c = a.remove_range(3,4)
[0, 2, 8, 5]
或指数范围为3至4

a.slice!(3..4)
a # => [0, 2, 8, 5]

用字符串操作尝试了一些时髦的东西。我想是O(4*M),如果这是一件事的话

a.join.gsub(/#{a.join[1..2]}/,'').split('').map{|i| i.to_i}
=> [0, 2, 4, 5]
a.join.gsub(/#{a.join[3..4]}/,'').split('').map{|i| i.to_i}
=> [0, 2, 8, 5]

是Ruby API/语法问题还是编码/算法问题?我不同意它“不存在”。它只是没有你所认为的名称。+David Hoelzer我很高兴知道它在那里。名称是什么?在您的示例中,
a
永不更改,这意味着您必须将结果复制到另一个数组,对吗?那么如何实现O(1)空间复杂度呢?@coderz你说得对。也许根本没有办法用Ruby实现O(1)。我只是想把它作为一个目标,这在c/c++中是可以实现的。
delete_at
操作是O(n)时间复杂度(请参阅),不符合时间复杂度要求。如果要删除元素,必须在同一索引中删除多次,或者按索引从最高索引到最低索引进行删除。请注意,这会改变数组。您可能希望引发
ArgumentError
异常,而不是返回
false
。其余部分也可以表示为切片(0…sp).concat(切片(ep+1..-1))
<代码>数组#concat比
+
更有效,因为它避免了创建两个临时数组。一个小问题是:当
if
语句在
if
end
之间只有一行时,一些人更喜欢编写(例如):
如果sp<0 | ep>size-1,则引发ArgumentError,我认为这是最直接(不是最酷)的方法:)@pierr小心
+
,除非你的数组总是很短。根据@DaveNewton注释将+更新为concat这很棘手,我不知道
。拒绝。使用_index
之类的东西。很酷。我听到有人说,“为什么格雷森不使用?而不是?来检查范围内的每个元素?”。啊,但是
include?
足够聪明,它知道,就像
cover?
一样,当端点是数字的时候,它就可以使用端点。这对我来说很好!
# Use: array.slice!(range)
a = [0,2,8,2,4,5,]

a.slice!(1..2)
a # => [0, 2, 4, 5]
a.slice!(3..4)
a # => [0, 2, 8, 5]
a.join.gsub(/#{a.join[1..2]}/,'').split('').map{|i| i.to_i}
=> [0, 2, 4, 5]
a.join.gsub(/#{a.join[3..4]}/,'').split('').map{|i| i.to_i}
=> [0, 2, 8, 5]