390

我在 Ruby 中有一系列元素

[2,4,6,3,8]

3例如,我需要删除具有值的元素

我怎么做?

4

15 回答 15

554

我想我已经弄清楚了:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]
于 2012-04-05T19:22:39.623 回答
252

借用评论中的特拉维斯,这是一个更好的答案:

我个人喜欢[1, 2, 7, 4, 5] - [7]哪个结果=> [1, 2, 4, 5]来自irb

我修改了他的答案,发现 3 是他的示例数组中的第三个元素。对于那些没有意识到 3 在数组中的位置 2 的人来说,这可能会导致一些混乱。

于 2014-03-17T21:08:48.770 回答
73

另外一个选项:

a = [2,4,6,3,8]

a -= [3]

这导致

=> [2, 4, 6, 8] 
于 2014-09-18T02:23:43.260 回答
66

我不确定是否有人说过这一点,但是 Array.delete() 和 -= value将删除数组中传递给它的值的每个实例。为了删除特定元素的第一个实例,您可以执行类似的操作

arr = [1,3,2,44,5]
arr.delete_at(arr.index(44))

#=> [1,3,2,5]

可能有更简单的方法。我并不是说这是最佳实践,但这是应该得到认可的。

于 2016-12-31T18:29:36.553 回答
36

假设您想在数组中的多个位置按值删除 3,我认为执行此任务的 ruby​​ 方法是使用 delete_if 方法:

[2,4,6,3,8,3].delete_if {|x| x == 3 } 

您还可以使用 delete_if 删除“数组数组”场景中的元素。

希望这能解决您的查询

于 2016-11-27T13:47:19.330 回答
30

我喜欢-=[4]其他答案中提到的删除值为4的元素的方式。

但是有这种方法:

[2,4,6,3,8,6].delete_if { |i| i == 6 }
=> [2, 4, 3, 8]

在“基本数组操作”中的某处提到map函数之后。

于 2015-06-26T01:36:06.733 回答
23

您可以简单地运行:

[2,4,6,3,8].delete(3)
于 2014-10-17T07:30:28.267 回答
21

A.delete_at(3) 3这里是位置。

于 2015-03-28T07:53:50.450 回答
15

以下是一些基准:

require 'fruity'


class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8]

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 4096 times. Test will take about 2 seconds.
# >> soziev is similar to barlop
# >> barlop is faster than steve by 2x ± 1.0
# >> steve is faster than rodrigo by 4x ± 1.0
# >> rodrigo is similar to niels

再次使用包含大量重复项的更大数组:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 1000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 16 times. Test will take about 1 second.
# >> steve is faster than soziev by 30.000000000000004% ± 10.0%
# >> soziev is faster than barlop by 50.0% ± 10.0%
# >> barlop is faster than rodrigo by 3x ± 0.1
# >> rodrigo is similar to niels

甚至更大,重复更多:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 100_000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test once. Test will take about 6 seconds.
# >> steve is similar to soziev
# >> soziev is faster than barlop by 2x ± 0.1
# >> barlop is faster than niels by 3x ± 1.0
# >> niels is similar to rodrigo
于 2016-03-28T23:43:46.920 回答
8

我改进了 Niels 的解决方案

class Array          
  def except(*values)
    self - values
  end    
end

现在你可以使用

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]
于 2015-11-20T14:06:21.917 回答
7

在 ruby​​ 中编译所有不同的删除选项

delete - 按值删除匹配的元素。如果多个值匹配,它将全部删除。如果您不关心出现的次数或确定单次出现,请使用此方法。

a = [2, 6, 3, 5, 3, 7]
a.delete(3)  # returns 3
puts a       # return [2, 6, 5, 7]

delete_at - 删除给定索引处的元素。如果您知道索引,请使用此方法。

# continuing from the above example
a.delete_at(2) # returns 5
puts a         # returns [2, 6, 7]

delete_if - 删除块为真的每个元素。这将修改数组。调用块时,数组会立即更改。

b = [1, 2, 5, 4, 9, 10, 11]
b.delete_if {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

拒绝- 这将返回新数组,其中包含给定块为假的元素。以此维持顺序。

c = [1, 2, 5, 4, 9, 10, 11]
c.reject {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

拒绝!- 与delete_if相同。调用块时,数组可能不会立即更改。

如果要从数组中删除多个值,最好的选择如下。

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
于 2020-01-24T17:40:03.740 回答
4

非破坏性去除首次出现:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)
于 2018-08-18T02:07:03.100 回答
4

如果您还想使此删除操作可链接,因此您可以删除一些项目并继续对结果数组进行链接操作,请使用tap

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4
于 2018-11-02T17:53:59.653 回答
3

你也可以猴子修补它。我从来不明白为什么 Ruby 有一个except方法 forHash但没有 for Array

class Array
  def except value
    value = value.kind_of(Array) ? value : [value]
    self - value
  end
end

现在你可以这样做:

[1,3,7,"436",354,nil].except(354) #=> [1,3,7,"436",nil]

或者:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]
于 2015-07-28T12:15:12.297 回答
3

因此,当您多次出现 3 并且只想删除第一次出现的 3 时,您可以简单地执行以下操作。

arr = [2, 4, 6, 3, 8, 10, 3, 12]

arr.delete_at arr.index 3

#This will modify arr as [2, 4, 6, 8, 10, 3, 12] where first occurrence of 3 is deleted. Returns the element deleted. In this case => 3.
于 2016-09-14T03:15:26.697 回答