Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.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
Arrays 如何找到大规模数组中的哪些项目多次出现?_Arrays_Ruby_Performance_Sorting_Unique - Fatal编程技术网

Arrays 如何找到大规模数组中的哪些项目多次出现?

Arrays 如何找到大规模数组中的哪些项目多次出现?,arrays,ruby,performance,sorting,unique,Arrays,Ruby,Performance,Sorting,Unique,这是一个非常简单的问题;哪些项目多次出现在列表中 array = ["mike", "mike", "mike", "john", "john", "peter", "clark"] 正确答案是[“迈克”,“约翰”] 看来我们可以做到: array.select{ |e| ary.count(e) > 1 }.uniq 问题解决了。但是等等!如果阵列真的很大怎么办: 1_000_000.times { array.concat("1234567890abcdefghijklmnopqr

这是一个非常简单的问题;哪些项目多次出现在列表中

array = ["mike", "mike", "mike", "john", "john", "peter", "clark"]
正确答案是
[“迈克”,“约翰”]

看来我们可以做到:

array.select{ |e| ary.count(e) > 1 }.uniq
问题解决了。但是等等!如果阵列真的很大怎么办:

1_000_000.times { array.concat("1234567890abcdefghijklmnopqrstuvwxyz".split('')) }
碰巧我需要弄清楚如何在合理的时间内做到这一点。我们在谈论数以百万计的唱片

值得一提的是,这个庞大的阵列实际上是10-20个较小阵列的总和。如果比较起来更容易,让我知道——我很困惑

我们说的是每个文件10000到10000000行,数百个文件

是这样的吗

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秒

这里还有两个解决方案,对这些方法和@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)
如果
s1
已包含
e
,则返回
nil
,在这种情况下,如果
smulti
尚未包含该元素,则将
e
添加到
smulti
。(请参阅。)
smulti
由该方法返回

使用
数组#差异

Array#difference
是我添加到Ruby核心的一种方法。另见我的答案

基准

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%

当然,
差异
,如果是Ruby核心的一部分,将用C进行编码并进行优化。

有点头脑风暴,但是如果我们将这些值输入到哈希表中,那么如果它们开始冲突,我们假设它是重复的?头脑风暴继续:假设100000000条目的32位散列需要一个高达4G字节的表。通过使用一个位集,每一位代表一个被占用的散列,可以将其压缩到116兆字节。这种方法需要通过两次数据传递来过滤掉潜在的重复项?不确定我是否理解较小阵列的比较注意:如果您确定每个阵列包含其他阵列中未出现的项目,则这只会返回相同的结果。我无法忘记您的头像。@CarySwoveland嘿,Cary,我不久前通过电子邮件向您寻求Ruby帮助。我想象我的化身是男高音歌手。你觉得呢?喜欢默认的散列初始化
counts=hash.new{124; hash,key{124; hash[key]=0}
你可以简化为
counts=hash.new(0)
。计数可以用每个_与_对象:counts=array.每个_与_对象(hash.new){item,akku akku akku[item]+=1}你忘记了
(0)
Hash.new(0)
中的
在您的最后一条评论中。Arghh。再次感谢。
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%