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


Answers:


481

我想我已经知道了:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]

188
我个人很喜欢[1, 2, 3, 4, 5] - [3]这结果=> [1, 2, 4, 5]irb
特拉维斯

24
如果有多个3项并且我们只想删除其中之一怎么办?(这是相关的,所以最好在这里问这个问题)
Navneet 2012年

113
请注意,.delete()将返回删除的值,而不是删除了值的修改后的数组。
约书亚·品特

23
要考虑的另一个结果是,delete对基础数组进行了突变,而-创建了一个新数组(返回给您),但没有删除值。根据您的用例,这两种方法都可能有意义。
srt32 2014年

2
@ user3721428,delete(3)不引用位置3的元素,而是删除匹配整数3的任何元素。它将删除所有出现的3,并且与数组的索引或位置无关。
bkunzi01 2016年

226

Travis的评论中借用,这是一个更好的答案:

我个人喜欢[1, 2, 7, 4, 5] - [7]这是=> [1, 2, 4, 5]irb

看到3是示例数组中的第三个元素,我修改了他的答案。对于那些没有意识到3在数组中的位置2的人来说,这可能会引起一些困惑。


21
正如srt32在答案中指出的那样,在使用.delete和之间有一个重要的区别-.delete将返回从数组中删除的值(如果有);-将不会。所以[ 1, 2, 3 ] - [ 2 ]会回来[ 1, 3 ],而[ 1, 2, 3 ].delete( 2 )会回来2
2014年

5
array - subArray不适用于Array of Arrays,但array.delete(subArray)可以。
萨钦

20
[1,2,3] - [2]和之间的非常重要的区别[1,2,3].delete(2)是该delete方法在创建新数组的同时修改了原始数组[1,2,3] - [3]
蒂莫西·科瓦廖夫

重新子数组(上面@Sachin的评论)“当然可以”,您只需要正确地表示即可: [1,2,[2],2,3,4] - [2]给您[1, [2], 3, 4],但是[1,2,[2],2,3,4] - [[2]]给您[1, 2, 2, 3, 4]。:-)
Tom Hundt

69

另外一个选项:

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

a -= [3]

导致

=> [2, 4, 6, 8] 

50

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

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

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

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


1
我一直在寻找一种方法来执行此操作,并且在重复的情况下仅删除元素的一个实例,这样效果很好!
xeroshogun

我认为这个答案是错误的,仅仅是因为arr.index()可能会出现nil
windmaomao

32

假设要在数组中的多个位置按值删除3,我认为执行此任务的红宝石方法将是使用delete_if方法:

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

您还可以在删除“数组数组”方案中的元素时使用delete_if。

希望这能解决您的查询


25

我喜欢-=[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>

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


但您不能只使用.delete(6)
Zac

@Zac当然可以,但是已经提到了该答案(非常简洁的-=方式, a-=[4]a=a-[4][3,4]-[4],我说我很喜欢),但是我想提及另一种可能的方式。
barlop

此方法还具有返回数组而不是删除元素的优点。
F.Webber



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

7
那么,什么是最好的?:)
Kirby

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]

您的解决方案无法在irb控制台上运行 2.2.1 :007 > [1, 2, 3, 4].except(3, 4) NoMethodError: undefined method except for [1, 2, 3, 4]:Array from (irb):7 from /usr/share/rvm/rubies/ruby-2.2.1/bin/irb:11:in <main>
hgsongra '16

1
要在IRB中声明,您需要将方法添加到Array class Array; def except(*values); self - values; end; end
Mark Swardstrom'3

3

您也可以用猴子修补它。我从来不明白为什么Ruby有一个except方法Hash但没有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]

1
您不需要value.kind_of(Array)测试。只需使用self - Array(value)
Sasgorilla

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.

3

首次出现的无损清除:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)

2

如果还希望使该删除操作可链接,那么可以删除某些项目并继续对结果数组进行链接操作,请使用tap

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4

1

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

删除 -删除匹配由值的元素。如果多个值匹配,它将全部删除。如果您不在乎出现的次数或确定只发生一次,请使用此方法。

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删除每个块为true的元素。这将修改数组。调用该块时,数组立即更改。

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

拒绝 -这将返回带有给定块为false的元素的新数组。以此维护订单。

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]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.