在Ruby中从数组中删除并返回被删除的元素

20

如何从数组中删除某些元素并选择它们?

例如:

class Foo 
  def initialize
    @a = [1,2,3,4,5,6,7,8,9]
  end

  def get_a
    return @a
  end
end

foo = Foo.new
b = foo.get_a.sth{ |e| e < 4 }
p b # => [1,2,3]
p foo.get_a # => [4,5,6,7,8,9,10]

我可以使用什么替代 foo.get_a.sth


你在 Foo 类中的实例变量 @a 没有任何作用,应该将其删除。 - sawa
问题被抽象化了,细节被删除了。你可以假设行@a = [1,2,3,4,5,6,7,8,9]是某个过程的结果。 - NewMrd
对不起!!我习惯了Java表单!!!:p - NewMrd
抽象工厂工厂在哪里?开玩笑的,但是认真地说,Ruby和Java有不同的文化,请使用更清晰的例子,可能涉及一些现实世界的对象等等。这很难阅读。 - boulder_ruby
5个回答

35

如果您不需要保留a的对象ID:

a = [1,2,3,4,5,6,7,8,9,10]
b, a = a.partition{|e| e < 4}
b # => [1, 2, 3]
a # => [4, 5, 6, 7, 8, 9, 10]

如果您需要保留a的对象标识符,则使用临时数组c

Translated:

如果您需要保留a的对象标识符,则使用临时数组c

a = [1,2,3,4,5,6,7,8,9,10]
b, c = a.partition{|e| e < 4}
a.replace(c)

1
很好的回答,但我无法更改 aasome_object.get_some_array 函数的结果。 - NewMrd
@NewMrd 为什么你不能改变它?一个变量就是一个变量,所以你总是可以将一个变量分配为该调用的结果,然后这个模式就可以正常工作。 - tadman
4
在这种情况下,你可以使用a.select { |e| e < 4 },它会返回通过测试的元素。 - Aaron Cronin
1
谢谢@sawa。我使用了some_object.set_some_array c而不是a.replace c - NewMrd

4
Rails 6 现在有这个功能:
a = [1, 2, 3]
#=> [1, 2, 3]
a.extract! { |n| n.even? }
#=> [2]
a
#=> [1, 3] 

2

如果您只删除一个项目,则不需要复制数组等操作:

array = [{ id: 1 }, { id: 2 }, {id: 3 }]
array.delete_at(array.find_index { |element| element[:id] == 1 })
#=> {:id=>1} 

1
这是我应用程序类似需求的完美解决方案。 - Jay
如果 find_index 返回 nil,那么这将失败。 - mountriv99

1
a = [1, 2, 3, 4]
a.dup - (a.delete_if(&:even?))
#=> [2, 4]

a
#=> [1, 3]

a = [1, 2, 3, 4]
b = a.dup - (a.delete_if { |e| e < 4 })
a
#=> [4]
b
#=> [1, 2, 3]

编辑:听起来你只是想要#select...

a = [1, 2, 3, 4]
a.select { |e| e < 3 }
#=> [1, 2]

如果有重复元素,则该块将对它们返回相同的结果,因此这不是什么问题! - Aaron Cronin
你能提供一个例子吗? - Aaron Cronin

0

我还是不相信 Ruby 的默认库中没有类似的方法。应该有一个与 #drop 方法等效的方法。肯定有一个可用的 gem 可以为数组类添加这个功能。但是当你可以编写自己的脚本时,谁还需要 gem 呢:

#in initializer somewhere
class Array
  def exclude(obj)
    x = self
    x.delete(obj)
    x
  end
end

我可能会向Ruby GitHub项目提交一个pull request,以便使用这个方法。这个超人补丁目前运行得非常好。


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