这是一个非常简单的问题;哪些项目不止一次出现在列表中?
array = ["mike", "mike", "mike", "john", "john", "peter", "clark"]
正确答案是["mike", "john"]
。
似乎我们可以这样做:
array.select{ |e| ary.count(e) > 1 }.uniq
问题解决了。可是等等!如果数组非常大,该怎么办:
1_000_000.times { array.concat("1234567890abcdefghijklmnopqrstuvwxyz".split('')) }
事实上,我需要弄清楚如何在合理的时间内完成这项工作。我们正在谈论数以百万计的记录。
对于它的价值,这个庞大的阵列实际上是10-20个较小阵列的总和。如果比较那些比较容易,请告诉我 - 我很难过。
我们正在谈论每个文件10,000到10,000,000行,数百个文件。
答案 0 :(得分:2)
喜欢
items = 30_000_000
array = items.times.map do
rand(10_000_000)
end
puts "Done with seeding"
puts
puts "Checking what items appear more than once. Size: #{array.size}"
puts
t1 = Time.now
def more_than_once(array)
counts = Hash.new(0)
array.each do |item|
counts[item] += 1
end
counts.select do |_, count|
count > 1
end.keys
end
res = more_than_once(array)
t2 = Time.now
p res.size
puts "Took #{t2 - t1}"
为你工作?
我的机器上的持续时间约为40秒。
答案 1 :(得分:1)
以下是另外两个解决方案,对这些方法和@Pascal的方法进行基准比较。
使用套件
require 'set'
def multi_set(arr)
s1 = Set.new
arr.each_with_object(Set.new) { |e, smulti| smulti.add(e) unless s1.add?(e) }.to_a
end
arr = ["mike", "mike", "mike", "john", "john", "peter", "clark"]
multi(arr)
#=> ["mike", "john"]
正在构建 s1
以包含arr
的所有不同元素。如果s1.add?(e)
已包含nil
,则s1
会返回e
,如果e
尚未smulti
,smulti
会被添加到smulti
包含该元素。 (请参阅Set#add?。)方法返回Array#difference
。
使用Array#difference
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
def multi_difference(arr)
arr.difference(arr.uniq).uniq
end
是我将proposed添加到Ruby核心的方法。另请参阅我的回答here。
def more_than_once(arr)
counts = Hash.new { |hash, key| hash[key] = 0 }
arr.each do |item|
counts[item] += 1
end
counts.select do |_, count|
count > 1
end.keys
end
require 'fruity'
items = 30_000_000
arr = items.times.map { rand 10_000_000 }
compare do
Pascal { more_than_once(arr) }
Set { multi_set(arr) }
Difference { multi_difference(arr) }
end
Running each test once. Test will take about 4 minutes.
Pascal is faster than Set by 19.999999999999996% ± 10.0%
Set is faster than Difference by 30.000000000000004% ± 10.0%
<强>基准强>
difference
当然,var what = ["jokes", "cats", "news", "weather", "sport"];
var do;
function start() {
do = what[Math.floor((Math.random() * what.length) + 1)];
}
start();
Document.write(do);
,如果是Ruby核心的一部分,将用C编码并进行优化。