[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Isolating non-unique items in an array

Jason Burgett

10/12/2006 3:25:00 PM

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.

--
Posted via http://www.ruby-....

15 Answers

Tim Pease

10/12/2006 3:42:00 PM

0

On 10/12/06, Jason Burgett <jasbur@gmail.com> 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.
>
> --
> Posted via http://www.ruby-....
>
>

class Array
def count( item )
return 0 unless self.include? item

c = 0
self.each {|i| c += 1 if i == item}
return c
end
end

ary = %w(a a a b c d d)
new_ary = ary.select {|item| ary.count(item) > 1}

counts = Hash.new {|h,k| h[k] = new_ary.count(k)}


It's not going to be fast, but it should work.

Blessings,
TwP

Jeff Schwab

10/12/2006 3:46:00 PM

0

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.

# Output:
# ["a", "a", "a", "d", "d"]
# {"a"=>3, "d"=>2}

def get_counts(keys)
counts = Hash.new(0)
keys.each {|k| counts[k] += 1 }
counts
end

def non_uniq(elements)
counts = get_counts(elements)
counts.delete_if {|k, v| v < 2 }
elements.select {|e| counts.key?(e) }
end

elements = ["a", "a", "a", "b", "c", "d", "d"]

p non_uniq(elements)
p get_counts(elements).delete_if {|k, v| v < 2 }

Jeff Schwab

10/12/2006 3:49:00 PM

0

Jeffrey Schwab wrote:
> 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.
>
> # Output:
> # ["a", "a", "a", "d", "d"]
> # {"a"=>3, "d"=>2}
>
> def get_counts(keys)
> counts = Hash.new(0)
> keys.each {|k| counts[k] += 1 }
> counts
> end
>
> def non_uniq(elements)
> counts = get_counts(elements)
> counts.delete_if {|k, v| v < 2 }
> elements.select {|e| counts.key?(e) }
> end

# Better:
def non_uniq(elements)
counts = get_counts(elements)
elements.select {|e| counts[e] > 1 }
end


>
> elements = ["a", "a", "a", "b", "c", "d", "d"]
>
> p non_uniq(elements)
> p get_counts(elements).delete_if {|k, v| v < 2 }

Alex Young

10/12/2006 3:52:00 PM

0

Tim Pease wrote:
> On 10/12/06, Jason Burgett <jasbur@gmail.com> 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.
>>
>> --
>> Posted via http://www.ruby-....
>>
>>
>
> class Array
> def count( item )
> return 0 unless self.include? item
>
> c = 0
> self.each {|i| c += 1 if i == item}
> return c
> end
> end
>
> ary = %w(a a a b c d d)
> new_ary = ary.select {|item| ary.count(item) > 1}
>

Better:

class Array
def counts # could be golfed, but clarity is king
result = Hash.new{0}
self.each {|a| result[a] += 1}
result
end
end

a = ["a", "a", "a", "b", "c", "d", "d"]
c = a.counts
a.reject{|b| c[b] == 1} # => ["a", "a", "a", "d", "d"]

--
Alex



Drew Olson

10/12/2006 4:03:00 PM

0

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

This should work:

a = ["a", "a", "a", "b", "c", "d", "d"]
a.uniq.map{|i| i if (a.map{|j| j if j==i}.length > 1)}

--
Posted via http://www.ruby-....

Ross Bamford

10/12/2006 4:04:00 PM

0

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


Drew Olson

10/12/2006 4:05:00 PM

0

Drew Olson wrote:
> 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
>
> This should work:
>
> a = ["a", "a", "a", "b", "c", "d", "d"]
> a.uniq.map{|i| i if (a.map{|j| j if j==i}.length > 1)}

Actually, so that you have them appear more than once you'd need to do:

a = ["a", "a", "a", "b", "c", "d", "d"]
a.map{|i| i if (a.map{|j| j if j==i}.length > 1)}

--
Posted via http://www.ruby-....

Jamey Cribbs

10/12/2006 4:22:00 PM

0

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.
>
>
Here's what I whipped up:

letters = ['a','a','a','b','c','d','d']
counts = {}

letters.each do |letter|
count = letters.find_all { |x| x == letter }.size
counts[letter] = count if count > 1
end

non_unique_letters = letters.find_all { |x| counts.has_key?(x) }

p counts
p non_unique_letters

Jamey

Confidentiality Notice: This email message, including any attachments, is for the sole use of the intended recipient(s) and may contain confidential and/or privileged information. If you are not the intended recipient(s), you are hereby notified that any dissemination, unauthorized review, use, disclosure or distribution of this email and any materials contained in any attachments is prohibited. If you receive this message in error, or are not the intended recipient(s), please immediately notify the sender by email and destroy all copies of the original message, including attachments.

WATANABE Hirofumi

10/12/2006 4:25:00 PM

0

Hi,

Jason Burgett <jasbur@gmail.com> writes:

> 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.

% irb
>> a = ["a", "a", "a", "b", "c", "d", "d"]
=> ["a", "a", "a", "b", "c", "d", "d"]
>> a.select{|i| a.grep(i).size > 1}
=> ["a", "a", "a", "d", "d"]

--
eban

Drew Olson

10/12/2006 4:28:00 PM

0

Tested, and it doesn't work, so scratch that...

--
Posted via http://www.ruby-....