如何从指定索引处的数组中删除元素,这些索引本身是否在数组中?

时间:2017-03-18 23:21:43

标签: arrays ruby

我使用的是Ruby 2.4。如果我有一组数组索引,并且我想删除这些索引处的所有元素,我该怎么做?我尝试了下面的内容,但它留下的东西

2.4.0 :005 > indexes_to_delete = [7, 8, 9]
 => [7, 8, 9]

2.4.0 :008 > a = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
 => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
2.4.0 :009 > indexes_to_delete.each do |index| a.delete_at(index) end
 => [7, 8, 9]
2.4.0 :010 > a
 => ["a", "b", "c", "d", "e", "f", "g", "i"]

注意结束数组。因为我从10开始,然后在数组中指定要删除的三个元素索引,所以我应该只有七个元素。但我有八个要素。如何调整我的语句以删除我指定的索引处的元素?

3 个答案:

答案 0 :(得分:3)

每次从数组中删除项目时,索引都会更改。

所以你可以这样做:

3.times { a.delete_at(7) }

与7,8,9的删除效果相同

或按照此处的建议使用slice!:{{3}}

a.slice!(7..9)

使用任意数组,我认为明显的选择是拒绝索引:

a.reject.with_index { |item, idx| indexes_to_delete.include? idx }

这是非变异的,因此您可以设置一个等于结果的变量。

答案 1 :(得分:1)

以下是一些方法。

indexes_to_delete = [3, 8, 9]
a =    ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]

<强>#1

indexes_to_delete.sort.reverse_each { |i| a.delete_at(i) }
a #=>  ["a", "b", "c",      "e", "f", "g", "h"] 

这会改变a。如果不需要,请使用aa.dup)的副本。

请记住,您必须按照索引的相反顺序删除元素。

#2

 a.values_at(*(0..a.size-1).to_a - indexes_to_delete)
   #=> ["a", "b", "c",      "e", "f", "g", "h"]

首先我们计算“守护者”

(0..a.size-1).to_a - indexes_to_delete 
  #=> [0, 1, 2, 4, 5, 6] 

这不会改变a。如果要变异a,请写

 a.replace(a.values_at(*(0..a.size-1).to_a - indexes_to_delete))
   #=> ["a", "b", "c",      "e", "f", "g", "h"] 
 a #=> ["a", "b", "c",      "e", "f", "g", "h"]

@maxple给出了第三种方式(reject.with_index),这对我来说是最好的。我怀疑三者之间存在显着的效率差异。

答案 2 :(得分:1)

您的问题是执行删除时索引会发生更改。所以最初不要删除。

a = ["a","b","c","d","e","f","g","h","i","j"]
to_delete = [7,8,9]
to_delete.each { |i| a[i] = nil }
a.compact!

将要删除的元素设置为nil,然后压缩数组以除去这些元素。

如果你想保留nil元素,但是你有一个你知道在数组中永远不会有的值,你可以做

MARK = special value
to_delete.each { |i| a[i] = MARK }
a.delete(MARK)