如何按值从数组中删除一个元素

Tam*_*iev 327 ruby arrays

我在Ruby中有一系列元素

[2,4,6,3,8]
Run Code Online (Sandbox Code Playgroud)

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

我怎么做?

Tam*_*iev 451

我想我已经弄明白了:

a = [2,4,6,3,8]
a.delete(3)
Run Code Online (Sandbox Code Playgroud)

  • 我个人喜欢`[1,2,3,4,5] - [3]`从`irb`得到`=> [1,2,4,5]`. (174认同)
  • 只是提醒一下.delete()将返回已删除的值,而不是已删除值的已修改数组. (112认同)
  • 如果有多个条目3并且我们只想删除其中一个,该怎么办?(这是相关的,所以在这里问这可能是最好的) (23认同)
  • 要考虑的另一个结果是`delete`会改变底层数组,而`-`会创建一个没有删除值的新数组(返回给你).根据您的使用情况,任何一种方法都可能有意义. (21认同)
  • @ user3721428,delete(3)不引用位置3中的元素,而是删除与整数3匹配的任何元素.它将删除所有出现的3并且与数组索引或位置无关. (2认同)
  • 对此要非常小心,如果您在活动记录数组上执行此操作,它实际上会从数据库中删除该元素 (2认同)

Abr*_*ram 213

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

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

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

  • 正如srt32在答案中指出的那样,在使用`.delete`和`-`之间有一个重要的区别.`.delete`将返回从Array中删除的值(如果有的话); `-`不会.所以`[1,2,3] - [2]`将返回`[1,3]`,而`[1,2,3] .delete(2)`将返回'2`. (21认同)
  • `[1,2,3] - [2]`和`[1,2,3] .delete(2)`之间非常重要的区别是`delete`方法**修改原始数组**,而` [1,2,3] - [3]`创建一个**新数组**. (19认同)
  • `array - subArray`不适用于**数组的数组**,但是`array.delete(subArray)`会有效. (3认同)

Ste*_*eve 65

另外一个选项:

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

a -= [3]
Run Code Online (Sandbox Code Playgroud)

结果

=> [2, 4, 6, 8] 
Run Code Online (Sandbox Code Playgroud)


小智 41

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

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

#=> [1,3,2,5]
Run Code Online (Sandbox Code Playgroud)

可能有一种更简单的方法.我不是说这是最佳做法,但它应该被认可.


Say*_*yan 28

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

[2,4,6,3,8,3].delete_if {|x| x == 3 } 
Run Code Online (Sandbox Code Playgroud)

您还可以使用delete_if删除"数组数组"方案中的元素.

希望这能解决您的疑问


bar*_*lop 24

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

但有这种方式:

irb(main):419:0> [2,4,6,3,8,6].delete_if{|i|i==6}
=> [2, 4, 3, 8]
irb(main):420:0>
Run Code Online (Sandbox Code Playgroud)

在提到函数后,在" 基本数组操作 " 中的某处提到过map.


ril*_*ham 21

你可以简单地运行:

[2,4,6,3,8].delete(3)
Run Code Online (Sandbox Code Playgroud)


Saw*_*iff 19

一个.delete_at(3) 3正在此间位置.


the*_*Man 14

以下是一些基准测试:

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

更重要的是更大的重复:

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
Run Code Online (Sandbox Code Playgroud)

  • 那么,最好的是什么?:) (7认同)

小智 7

我改进了Niels的解决方案

class Array          
  def except(*values)
    self - values
  end    
end
Run Code Online (Sandbox Code Playgroud)

现在你可以使用了

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)


dgi*_*rez 7

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

\n\n
[2, 4, 6, 3, 8].tap { |ary|\xc2\xa0ary.delete(3) }.count #=> 4\n
Run Code Online (Sandbox Code Playgroud)\n


小智 7

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

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

a = [2, 6, 3, 5, 3, 7]
a.delete(3)  # returns 3
puts a       # return [2, 6, 5, 7]
Run Code Online (Sandbox Code Playgroud)

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

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

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

b = [1, 2, 5, 4, 9, 10, 11]
b.delete_if {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]
Run Code Online (Sandbox Code Playgroud)

拒绝- 这将返回包含给定块为假的元素的新数组。顺序是这样维护的。

c = [1, 2, 5, 4, 9, 10, 11]
c.reject {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]
Run Code Online (Sandbox Code Playgroud)

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

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

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
Run Code Online (Sandbox Code Playgroud)