我在 Ruby 中有一系列元素
[2,4,6,3,8]
3
例如,我需要删除具有值的元素
我怎么做?
我想我已经弄清楚了:
a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]
借用评论中的特拉维斯,这是一个更好的答案:
我个人喜欢
[1, 2, 7, 4, 5] - [7]
哪个结果=> [1, 2, 4, 5]
来自irb
我修改了他的答案,发现 3 是他的示例数组中的第三个元素。对于那些没有意识到 3 在数组中的位置 2 的人来说,这可能会导致一些混乱。
另外一个选项:
a = [2,4,6,3,8]
a -= [3]
这导致
=> [2, 4, 6, 8]
我不确定是否有人说过这一点,但是 Array.delete() 和 -= value将删除数组中传递给它的值的每个实例。为了删除特定元素的第一个实例,您可以执行类似的操作
arr = [1,3,2,44,5]
arr.delete_at(arr.index(44))
#=> [1,3,2,5]
可能有更简单的方法。我并不是说这是最佳实践,但这是应该得到认可的。
假设您想在数组中的多个位置按值删除 3,我认为执行此任务的 ruby 方法是使用 delete_if 方法:
[2,4,6,3,8,3].delete_if {|x| x == 3 }
您还可以使用 delete_if 删除“数组数组”场景中的元素。
希望这能解决您的查询
我喜欢-=[4]
其他答案中提到的删除值为4的元素的方式。
但是有这种方法:
[2,4,6,3,8,6].delete_if { |i| i == 6 }
=> [2, 4, 3, 8]
在“基本数组操作”中的某处提到map
函数之后。
您可以简单地运行:
[2,4,6,3,8].delete(3)
A.delete_at(3)
3
这里是位置。
以下是一些基准:
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
我改进了 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]
在 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]
非破坏性去除首次出现:
a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)
如果您还想使此删除操作可链接,因此您可以删除一些项目并继续对结果数组进行链接操作,请使用tap
:
[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4
你也可以猴子修补它。我从来不明白为什么 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]
因此,当您多次出现 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.