Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 在大列表中查找重复编号的最快方法_Ruby_Algorithm_Duplicates - Fatal编程技术网

Ruby 在大列表中查找重复编号的最快方法

Ruby 在大列表中查找重复编号的最快方法,ruby,algorithm,duplicates,Ruby,Algorithm,Duplicates,我正在处理一个大的ID列表(顺序为10^5)(是长数据类型)。我必须在身份证列表中找到重复的身份证。但我只能使用ruby 在这里,我找到了一种方法来做到这一点。 我将遍历列表并将Id放入哈希,但在放入哈希之前,我将检查它是否已经在哈希中 我不确定RUBY中哈希的复杂性 请给我一个更好的主意。为什么不使用Set require 'set' set = Set.new numbers.each do |number| puts "Number #{number} is already in t

我正在处理一个大的ID列表(顺序为10^5)(是长数据类型)。我必须在身份证列表中找到重复的身份证。但我只能使用ruby

在这里,我找到了一种方法来做到这一点。 我将遍历列表并将Id放入哈希,但在放入哈希之前,我将检查它是否已经在哈希中

我不确定RUBY中哈希的复杂性


请给我一个更好的主意。

为什么不使用
Set

require 'set'

set = Set.new
numbers.each do |number|
  puts "Number #{number} is already in the set" unless set.add?(number)
end
或者简单地查找重复项:

require 'set'
set = Set.new
duplicates = numbers.reject { |number| set.add?(number) } 
让我们看看上面是怎么说的:


编辑:更新了基准中的重复发现并更新了结果。

你的想法听起来不错。它真的慢吗?请分享您的结果。是什么让您认为Ruby中哈希的复杂性与其他语言不同?只要加载因子不太接近1,哈希通常被认为需要O(1)时间。一种方法是尝试对列表进行排序,然后以2:x.sort.each_cons(2)为单位对其进行迭代。选择{x,y | x==y}.map(&:first)。uniqGood解决方案。请注意,这相当于原始海报的建议(使用
散列
)。解决方案是
O(n)
。是的,除了可能使用更少的内存(取决于实现)外,几乎是一样的。理论上是这样,但实际上,是否有任何实现不使用
哈希
来处理
?可能现在没有,但将来可能会更改。您的实现缺少收集重复项的功能。@KARASZIIstván检查所有代码。。。有三种方法产生三种不同的基准。最后一个等于你的解决方案。我检查了你的代码,这就是我写评论的原因。您使用计数器创建了一个散列,但您需要从这些散列中获取副本,而这在您的基准测试中是缺失的。@KARASZIIstván我已经更新了示例中的代码。谢谢你指出这一点。但是你需要把这一部分放到基准块中,因为这也需要包括在数字中,否则你就是在比较桃子和苹果。
require 'benchmark'
require 'set'


def rand_n(n, max)
  randoms = Array.new
  loop do
    randoms << rand(max)
    return randoms.to_a if randoms.size >= n
  end
end

numbers = rand_n(10000, 10000000)

counter = Hash.new
time = Benchmark.measure do
  for number in numbers
    if counter.has_key?(number)
      counter[number] = counter[number]+1
    else
      counter[number]=1
    end
  end
duplicates = counter.select{|k,v| v > 1}
end
puts time

time1 = Benchmark.measure do
  counts = Hash.new{|h,k| h[k] = 0 }
  numbers.each{|n| counts[n] +=1}
  duplicates = counts.select{|k,v| v > 1}
end
puts time1

set = Set.new
time2 = Benchmark.measure do
  duplicates = numbers.reject { |number| set.add?(number) }
end

puts time2
  0.000000   0.000000   0.000000 (  0.006114)
  0.010000   0.000000   0.010000 (  0.008529)
  0.010000   0.000000   0.010000 (  0.006098)