Ross Bamford
10/12/2006 4:04:00 PM
On Fri, 2006-10-13 at 00:24 +0900, Jason Burgett wrote:
> I'm basically trying to the opposite of .uniq Let's say I have an array:
>
> ["a", "a", "a", "b", "c", "d", "d"]
>
> I would like to boil this down by first tossing the values that only
> appear once. Which leaves me with:
>
> ["a", "a", "a", "d", "d"]
>
> Then I need to somehow determine that "a" appears 3 times and "d"
> appears 2 times. Any help would be great. Thanks.
>
There are bound to be better ways, but you could try something like:
a = ["a", "a", "a", "b", "c", "d", "d"]
# => ["a", "a", "a", "b", "c", "d", "d"]
hsh = a.inject(Hash.new{|h,k| h[k] = 0}) {|h,v| h[v] += 1 ; h}.reject!
{|k,v| v == 1}
# => {"a"=>3, "d"=>2}
hsh['a']
# => 3
hsh['d']
# => 2
Depending on how you're using the results, You could also run a second
inject to reverse the lookup:
rhsh = hsh.inject(Hash.new { |h,k| h[k] = [] }) { |h,(k,v)| h[v] << k ;
h }
# => {2=>["d"], 3=>["a"]}
(2..rhsh.keys.max).each { |i| puts "count #{i}: #{rhsh[i]}" }
# count 2: d
# count 3: a
If you went with this way, I guess you could forget about getting rid of
the 1s with reject!, since you could just ignore the 1 key in the
rhsh...
--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk