如何索引数组中的重复项?

时间:2011-09-30 09:52:28

标签: ruby

从以下数组(散列)开始:

[
  {:name=>"site a", :url=>"http://example.org/site/1/"}, 
  {:name=>"site b", :url=>"http://example.org/site/2/"}, 
  {:name=>"site c", :url=>"http://example.org/site/3/"}, 
  {:name=>"site d", :url=>"http://example.org/site/1/"}, 
  {:name=>"site e", :url=>"http://example.org/site/2/"}, 
  {:name=>"site f", :url=>"http://example.org/site/6/"},
  {:name=>"site g", :url=>"http://example.org/site/1/"}
]

如何添加重复网址的索引,如下所示:

[
  {:name=>"site a", :url=>"http://example.org/site/1/", :index => 1}, 
  {:name=>"site b", :url=>"http://example.org/site/2/", :index => 1}, 
  {:name=>"site c", :url=>"http://example.org/site/3/", :index => 1}, 
  {:name=>"site d", :url=>"http://example.org/site/1/", :index => 2}, 
  {:name=>"site e", :url=>"http://example.org/site/2/", :index => 2}, 
  {:name=>"site f", :url=>"http://example.org/site/6/", :index => 1},
  {:name=>"site g", :url=>"http://example.org/site/1/", :index => 3}
]

3 个答案:

答案 0 :(得分:5)

我会使用哈希来跟踪索引。 一次又一次地扫描先前的条目似乎效率低下

counts = Hash.new(0)
array.each { | hash | 
  hash[:index] = counts[hash[:url]] = counts[hash[:url]] + 1
}

或者有点清洁

array.each_with_object(Hash.new(0)) { | hash, counts | 
  hash[:index] = counts[hash[:url]] = counts[hash[:url]] + 1
}

答案 1 :(得分:3)

array = [
  {:name=>"site a", :url=>"http://example.org/site/1/"}, 
  {:name=>"site b", :url=>"http://example.org/site/2/"}, 
  {:name=>"site c", :url=>"http://example.org/site/3/"}, 
  {:name=>"site d", :url=>"http://example.org/site/1/"}, 
  {:name=>"site e", :url=>"http://example.org/site/2/"}, 
  {:name=>"site f", :url=>"http://example.org/site/6/"},
  {:name=>"site g", :url=>"http://example.org/site/1/"}
]

array.inject([]) { |ar, it| 
    count_so_far = ar.count{|i| i[:url] == it[:url]}
    it[:index] = count_so_far+1
    ar << it
}
#=>
[
  {:name=>"site a", :url=>"http://example.org/site/1/", :index=>1}, 
  {:name=>"site b", :url=>"http://example.org/site/2/", :index=>1}, 
  {:name=>"site c", :url=>"http://example.org/site/3/", :index=>1}, 
  {:name=>"site d", :url=>"http://example.org/site/1/", :index=>2}, 
  {:name=>"site e", :url=>"http://example.org/site/2/", :index=>2}, 
  {:name=>"site f", :url=>"http://example.org/site/6/", :index=>1}, 
  {:name=>"site g", :url=>"http://example.org/site/1/", :index=>3}
]

答案 2 :(得分:0)

如果我希望它有效率,我会写:

items_with_index = items.inject([[], {}]) do |(output, counts), h|
  new_count = (counts[h[:url]] || 0) + 1
  [output << h.merge(:index => new_count), counts.update(h[:url] => new_count)]
end[0]