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]