在数组中返回恰好存在一次的元素

时间:2013-07-24 16:09:16

标签: ruby arrays

我是Ruby的初学者。有人可以帮我写代码吗?

给定一个数组,返回数组中恰好存在一次的元素。

例如,它应该通过以下测试用例:

  • 返回[1,4,5],给定[1,2,2,3,3,4,5]
  • 返回[1,3],给定[1,2,2,3,4,4]

3 个答案:

答案 0 :(得分:5)

将项目放入数组中。 a = [1,2,2,3,4,4]然后运行一些过滤器以获取所需的项目。

a.group_by { |x| x }.reject { |k,v| v.count > 1 }.keys

#=> [1,3]

已更新使用Stefan的keys建议。

答案 1 :(得分:4)

a = [1,2,2,3,3,4,5]
p a.select{|i| a.count(i) == 1}
# >> [1, 4, 5]


a = [1,2,2,3,4,4]
p a.select{|i| a.count(i) == 1}
# >> [1, 3]

<强>基准

require 'benchmark'

a = [1,2,2,3,3,4,5]

n = 1000000
Benchmark.bm(15) do |x|
  x.report('priti') { n.times { a.select{|i| a.count(i) == 1} } }
  x.report('Jason') { n.times { a.group_by { |x| x }.reject { |k,v| v.count > 1 }.keys } }
  x.report('rogerdpack2') { n.times {
    bad = {}
    good = {}
    a.each{|v|
      if bad.key? v
        # do nothing
      else
        if good.key? v
          bad[v] = true
          good.delete(v)
        else
          good[v] = true;
        end
      end
    }
    good.keys            
  }
 }
end

有了这个结果

 priti             3.152000   0.000000   3.152000 (  3.247000)
 Jason             4.633000   0.000000   4.633000 (  4.845000)
 rogerdpack2       3.853000   0.000000   3.853000 (  3.886000)

并使用更大的数组:

要求'基准'

a = [1,2,2,3,3,4,5] * 5 + [33,34]

n = 1000000
Benchmark.bm(15) do |x|
  x.report('priti') { n.times { a.select{|i| a.count(i) == 1} } }
  x.report('Jason') { n.times { a.group_by { |x| x }.reject { |k,v| v.count > 1 }.keys } }
  x.report('rogerdpack2') { n.times {
    bad = {}
    good = {}
    a.each{|v|
      if bad.key? v
        # do nothing
      else
        if good.key? v
          bad[v] = true
          good.delete(v)
        else
          good[v] = true;
        end
      end
    }
    good.keys            
  }
 }
 x.report('priti2') { n.times { a.uniq.select{|i| a.count(i) == 1} }}
end

你得到结果:

                  user     system      total        real
 priti            60.435000   0.000000  60.435000 ( 60.769151)
 Jason            10.827000   0.016000  10.843000 ( 10.978195)
 rogerdpack2       9.141000   0.000000   9.141000 (  9.213843)
 priti2           15.897000   0.000000  15.897000 ( 16.007201)

答案 2 :(得分:0)

这是另一种选择:

a = [1,2,2,3,3,4,5]
b = {}
a.each{|v|
  b[v] ||= 0
  b[v] += 1
}
b.select{|k, v| v == 1}.keys

这里有一个可能更快的(虽然更复杂),它被硬编码以查找“刚刚列出一次”的项目:

a = [1,2,2,3,3,4,5]
bad = {}
good = {}
a.each{|v|
  if bad.key? v
    # do nothing
  else
    if good.key? v
      bad[v] = true
      good.delete(v)
    else
      good[v] = true;
    end
  end
}
good.keys