如何从数组中删除另一个数组中索引处的元素

时间:2015-08-24 15:51:02

标签: arrays ruby

我有两个数组,一个包含数据,另一个包含索引。我想知道是否有一些很好的方法可以删除dataindexes中给出的位置中的元素。我可以做简单的迭代,但我想知道最短的方法是什么:

data = ['a','b','c','a','b','c','a','b','c']
indexes = [2,5,8]

//some code here

当索引恰好与数组索引中的数字一致时,data中的元素消失了。它应该是这样的:

['a','b','a','b','a','b']

4 个答案:

答案 0 :(得分:5)

data.values_at(*data.each_index.to_a - indexes)
# => ["a", "b", "a", "b", "a", "b"]

答案 1 :(得分:4)

我将按以下方式进行:

data = ['a','b','c','a','b','c','a','b','c']
indexes = [2,5,8]
data.values_at(*(0...data.size).to_a - indexes)
# => ["a", "b", "a", "b", "a", "b"]

答案 2 :(得分:4)

不经迭代地完成它可能看起来是一个很好的目标,但正确完成迭代将会非常快。

基准非常重要:

require 'benchmark'

DATA = ['a','b','c','a','b','c','a','b','c']
INDEXES = [2,5,8]

def ttm(data)
  d2 = data.dup
  INDEXES.sort.reverse.each{ |i| d2.delete_at(i) }
  d2
end

def devon_parsons(data)
  new_data = data.each_with_index.reject do |value,index|
    INDEXES.include? index
  end.map(&:first)
  new_data
end

def arup_rakshit(data)
  data.values_at(*(0...data.size).to_a - INDEXES)
end

def sawa(data)
  data.values_at(*data.each_index.to_a - INDEXES)
end

确保它是苹果对苹果的测试:

ttm(DATA)           # => ["a", "b", "a", "b", "a", "b"]
devon_parsons(DATA) # => ["a", "b", "a", "b", "a", "b"]
arup_rakshit(DATA)  # => ["a", "b", "a", "b", "a", "b"]
sawa(DATA)          # => ["a", "b", "a", "b", "a", "b"]

运行基准测试:

n = 100_000 
Benchmark.bm(13) do |b|
  b.report('ttm:')          { n.times { ttm(DATA)           } }
  b.report('devon_parsons') { n.times { devon_parsons(DATA) } }
  b.report('arup_rakshit')  { n.times { arup_rakshit(DATA)  } }
  b.report('sawa')          { n.times { sawa(DATA)          } }
end

结果是:

# >>                     user     system      total        real
# >> ttm:            0.130000   0.000000   0.130000 (  0.127559)
# >> devon_parsons   0.530000   0.000000   0.530000 (  0.535929)
# >> arup_rakshit    0.250000   0.000000   0.250000 (  0.255295)
# >> sawa            0.300000   0.010000   0.310000 (  0.305376)

如果数据大小增加:

DATA2 = DATA * 100
Benchmark.bm(13) do |b|
  b.report('ttm:')          { n.times { ttm(DATA2)           } }
  b.report('devon_parsons') { n.times { devon_parsons(DATA2) } }
  b.report('arup_rakshit')  { n.times { arup_rakshit(DATA2)  } }
  b.report('sawa')          { n.times { sawa(DATA2)          } }
end

结果确实发生了变化:

# >>                     user     system      total        real
# >> ttm:            0.320000   0.090000   0.410000 (  0.420074)
# >> devon_parsons  39.170000   0.080000  39.250000 ( 39.265062)
# >> arup_rakshit    9.950000   0.010000   9.960000 (  9.975699)
# >> sawa            9.940000   0.020000   9.960000 (  9.959036)

测试阵列大小变化时发生的事情非常重要。随着阵列的增长,在小阵列上快速运行的内容会急剧减慢。而且,通常情况下,做某事的好方法变得非常缓慢,因为存在隐性成本。基准测试帮助我们解决这些问题。

注意:使用sort.reverse非常重要。没有这些,阵列将被破坏。

  

sort可以进一步改进为sort_by(&:本身)

require 'benchmark'

array = (0..99).to_a.shuffle
n = 100_000 

Benchmark.bm(7) do |b|
  b.report('sort:')    { n.times { array.sort              } }
  b.report('sort_by:') { n.times { array.sort_by(&:itself) } }
end

导致:

              user     system      total        real
sort:     0.460000   0.010000   0.470000 (  0.480236)
sort_by:  3.600000   0.030000   3.630000 (  3.627871)

增加数组大小:

array = (0..999).to_a.shuffle
Benchmark.bm(13) do |b|
  b.report('sort:')    { n.times { array.sort              } }
  b.report('sort_by:') { n.times { array.sort_by(&:itself) } }
end

导致:

                    user     system      total        real
sort:           9.520000   0.120000   9.640000 (  9.659246)
sort_by:       53.530000   0.720000  54.250000 ( 54.321285)

答案 3 :(得分:1)

new_data = data.each_with_index.reject do |value,index|
  indexes.include? index
end.map(&:first)

这次实际有效的新答案 - 它在O(n ^ 2)中运行,并且我没有看到这样做的方法而根本没有迭代索引。