我是 Ruby 的初学者。有人可以帮我为此编写代码吗?
给定一个数组,返回数组中只出现一次的元素。
例如,它应该通过以下测试用例:
- 返回
[1,4,5]
,给定[1,2,2,3,3,4,5]
- 返回
[1,3]
,给定[1,2,2,3,4,4]
将项目放入数组中。 a = [1,2,2,3,4,4]
然后运行一些过滤器来获取您想要的项目。
a.group_by { |x| x }.reject { |k,v| v.count > 1 }.keys
#=> [1,3]
更新了 Stefan 的keys
建议。
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)
这是另一种选择:
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