如何在Ruby中删除数组的末尾元素

12

Array#drop可以删除数组中的前n个元素。那么,有什么好方法可以删除数组的最后m个元素?或者,有什么好方法可以保留数组的中间元素(大于n,小于m)?


1
由于在Ruby中可以使用范围索引数组,因此将中间元素分配给新数组并使用它可能很方便。 foo = [1,2,3,4,5,6,7,8] => [1, 2, 3, 4, 5, 6, 7, 8] bar = foo[2..4] => [3, 4, 5] - Deathbob
8个回答

29

这正是 Array#pop 的用途:

x = [1,2,3]
x.pop(2) # => [2,3]
x # => [1]

@ggPeti:我知道这一点。问题的标题似乎暗示OP确实想要更改原始数组。 - Marc-André Lafortune
这是正确的答案,考虑到 OP 的要求 删除 最后 m 个元素。Pop 会从原始数组中删除它们,而 drop 或 slice 则会创建一个新数组。 - Trevor

9
您可以使用Array#slice方法,例如:
[1,2,3,4,5,6].slice(1..4) # => [2, 3, 4, 5]

或者
a = [1,2,3,4,5,6]
a.take 3 # => [1, 2, 3]
a.first 3 # => [1, 2, 3]
a.first a.size - 1 # to get rid of the last one

2
还有Array#slice!,当需要原地修改数组时可以使用。 - Victor Deryagin
Array#slice! 似乎与 Array#slice 没有任何不同。 - B Seven

4

drop(删除前n个元素)的最直接相反操作是 take,它保留前n个元素(还有类似于drop_whiletake_while)。

Slice 允许您通过指定范围或偏移量和长度返回数组的子集。当传递范围作为参数或传递2个数字时,Array#[]的行为相同。


1

我希望返回的值是没有被删除元素的数组。我在这里找到了几个解决方案,觉得还不错:

count = 2
[1, 2, 3, 4, 5].slice 0..-(count + 1) # => [1, 2, 3]
[1, 2, 3, 4, 5].tap { |a| a.pop count } # => [1, 2, 3]

但是我发现另一个解决方案更易读,如果数组的顺序不重要的话(在我的情况下,我正在删除文件):

count = 2
[1, 2, 3, 4, 5].reverse.drop count # => [3, 2, 1]

如果需要保留顺序,您可以在其中再添加一个 .reverse ,但我认为此时我更喜欢使用 tap 解决方案。

1

这将删除最后 n 个元素:

a = [1,2,3,4,5,6]
n = 4
p a[0, (a.size-n)]

#=> [1, 2]

n = 2
p a[0, (a.size-n)]
#=> [1, 2, 3, 4]    

关于“中间”元素:

min, max = 2, 5
p a.select {|v| (min..max).include? v }
#=> [2, 3, 4, 5]

0

您可以以非破坏性的方式实现与Array#pop相同的效果,而无需知道数组的长度:

a = [1, 2, 3, 4, 5, 6]
b = a[0..-2]
# => [1, 2, 3, 4, 5]
n = 3 # if we want drop the last n elements
c = a[0..-(n+1)]
# => [1, 2, 3]

0

Array#delete_at() 是删除数组最后一个元素的最简单方法,如下所示

arr = [1,2,3,4,5,6]
arr.delete_at(-1)
p arr # => [1,2,3,4,5]

如果要删除数组的一个或多个段落,请使用其他答案中的方法。


Vijay,你说“你必须再次调用arr才能获得[1,2,3,4,5]”这一评论毫无意义。你确实需要再次调用arr才能看到delete_at方法的效果。但是,对于在数组上运行的任何方法或任何其他类型的数据,都是如此。我的答案仍然是对OP提出的问题的有效解决方案。 - Mr. J
1
抱歉,太晚了。我错过了 arr 值的 puts。我已经删除了我的评论。 - Vijay

-2

你也可以添加一些方法

class Array

  # Using slice
  def cut(n)
    slice(0..-n-1)
  end

  # Using pop
  def cut2(n)
    dup.tap{|x| x.pop(n)}
  end

  # Using take
  def cut3(n)
    length - n >=0 ? take(length - n) : []
  end

end

[1,2,3,4,5].cut(2)
 => [1, 2, 3] 

正如我在这里看到的http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-pop,它是一个bang!方法,返回弹出的元素而不是结果数组,你应该使用dup或在对象的tap中使用它,例如ary.tap{|x| x.drop(2)}。 - Shtirlic
1
实际上,你的方法对应于 last(n)。还要注意,在你的方法中不需要使用 length - Marc-André Lafortune
#last 返回self的最后一个或多个元素。如果数组为空,则第一种形式返回nil。我的方法通过n截取尾部并返回self。 - Shtirlic
@Marc-AndréLafortune,这与我的my_array.dup.tap{|x| x.pop(n)}是一样的。 - Shtirlic
通常情况下,猴子补丁本地代码是不好的实践。 - thisismydesign

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接