Find that number is repeated more and less times in an array

Hi all.

I'm trying to find a function to find the number that is repeated over
and the least is repeated within an array. I tried a lot of things but I
can not make it work.

For example:

a = [1 2 2 3 5 4 6 2 6 5 4]

I calculate the number that is repeated over and less repeats and if
possible to calculate something like this for example:

=> With 0 repeats found the number 1.3, etc.
=> With 1 repetition was found the number: 4, etc.
=> With 2 repetitions was found the number 5, etc.

Thanks.

···

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

Hi,

I don't understand what you're saying.

OK, you have a given number n. Are you looking for all elements that
occur *at least* n times in the array?

To count the number of occurences, you can use Enumerable#inject:

array = [1, 2, 2, 3, 2, 5]
element = 2
element_count = array.inject 0 do |count, x|
  count + (x == element ? 1 : 0)
end

Or a more lowlevel solution:

array = [1, 2, 2, 3, 2, 5]
element = 2
element_count = 0
array.each do |x|
  element_count += 1 if x == element
end

···

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

=> With 0 repeats found the number 1.3, etc.
=> With 1 repetition was found the number: 4, etc.
=> With 2 repetitions was found the number 5, etc.

fire up irb or pry, and play w ruby,
eg,

a. group_by{|x|x}.group_by{|x,y| y.size-1}.each_with_object({}){|(k,v),h| h[k] = v.flatten.uniq}

=> {0=>[1, 3], 2=>[2], 1=>[5, 4, 6]}

···

On Sun, Jul 8, 2012 at 8:32 AM, Joao Silva <lists@ruby-forum.com> wrote:

Hash[a.group_by{|x|a.count(x)-1}.map{|k,v|[k,v.uniq]}]
=>{0=>[1, 3], 2=>[2], 1=>[5, 4, 6]}

or
a.group_by{|x|a.count(x)-1}.each_with_object({}){|(k,v),h|h[k]=v.uniq}
=>{0=>[1, 3], 2=>[2], 1=>[5, 4, 6]}

Benchmark testing:

Benchmark.bm do |x|
x.report { n.times {
  a.group_by{|x|x}.group_by{|x,y|
y.size-1}.each_with_object({}){|(k,v),h|
    h[k] =v.flatten.uniq
  }
}}
x.report { n.times {
  Hash[a.group_by{|x|a.count(x)-1}.map{|k,v|[k,v.uniq]}]
}}
x.report { n.times {
  a.group_by{|x|a.count(x)-1}.each_with_object({}){|(k,v),h|h[k]=v.uniq}
}}
end

n = 50000
       user system total real
   0.920000 0.000000 0.920000 ( 0.943945)
   0.730000 0.000000 0.730000 ( 0.732669)
   0.740000 0.000000 0.740000 ( 0.742029)

n = 500000
       user system total real
   9.040000 0.000000 9.040000 ( 9.062923)
   7.330000 0.000000 7.330000 ( 7.382192)
   7.070000 0.000000 7.070000 ( 7.085146)

···

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

Joao Silva wrote in post #1067849:

a = [1 2 2 3 5 4 6 2 6 5 4]

I calculate the number that is repeated over and less repeats and if
possible to calculate something like this for example:

=> With 0 repeats found the number 1.3, etc.
=> With 1 repetition was found the number: 4, etc.
=> With 2 repetitions was found the number 5, etc.

Do it in steps. First count the number of times each value is seen:

a = [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
counts = Hash.new(0)
a.each { |val| counts[val] += 1 }
# optional: counts = counts.sort_by { |val,count| count }
counts.each do |val,count|
  puts "With #{count-1} repeats found the number #{val}"
end

This is a starting point. Then you can look at grouping together values
with the same count.

a = [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
counts = Hash.new(0)
a.each { |val| counts[val] += 1 }
groups = {}
counts.each do |val,count|
  groups[count] ||=
  groups[count] << val
end
groups.each do |count,vals|
  puts "With #{count-1} repeats found #{vals.sort.join(", ")}"
end

When you're clear what's happening here then you can look at the more
compact versions using group_by.

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote in post #1067902:

a = [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
counts = Hash.new(0)
a.each { |val| counts[val] += 1 }
groups = {}
counts.each do |val,count|
  groups[count] ||=
  groups[count] << val
end
groups.each do |count,vals|
  puts "With #{count-1} repeats found #{vals.sort.join(", ")}"
end

One last thing, how do I print the results that I stay in order, because
the above code prints:

With 0 repeats found 1, 3
With 2 repeats found 2
With 1 repeats found 4, 5, 6

and I seek it to print in order:

With 0 repeats found 1, 3
With 1 repeats found 4, 5, 6
With 2 repeats found 2

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote in post #1067902:

a = [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
counts = Hash.new(0)
a.each { |val| counts[val] += 1 }
groups = {}
counts.each do |val,count|
  groups[count] ||=
  groups[count] << val
end
groups.each do |count,vals|
  puts "With #{count-1} repeats found #{vals.sort.join(", ")}"
end

One last thing, how do I print the results that I stay in order, because
the above code prints:

With 0 repeats found 1, 3
With 2 repeats found 2
With 1 repeats found 4, 5, 6

and I seek it to print in order:

groups.sort.each do |count,vals|
  puts "With #{count-1} repeats found #{vals.sort.join(", ")}"
end

With 0 repeats found 1, 3
With 1 repeats found 4, 5, 6
With 2 repeats found 2

I think you should read a little bit about classes Array, Hash and
module Enumerable, and try yourself things around in IRB until you
feel more comfortable about how to use many of the facilities they
provide.

Jesus.

···

On Sun, Jul 8, 2012 at 10:13 PM, Joao Silva <lists@ruby-forum.com> wrote:

Alternative solution

irb(main):001:0> a = [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
=> [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
irb(main):002:0> max=0; counts = a.inject(Hash.new(0)) {|c, x|
cc=(c+=1); max=cc if cc>max; c}
=> {1=>1, 2=>3, 3=>1, 5=>2, 4=>2, 6=>2}
irb(main):003:0> 1.upto(max){|r| printf "With %d repeats: %p\n", r,
counts.select {|k,v| v==r}.map{|k,v|k} }
With 1 repeats: [1, 3]
With 2 repeats: [5, 4, 6]
With 3 repeats: [2]
=> 1

(Explanation omitted for pedagogical reasons.)

Have fun!

robert

···

On Mon, Jul 9, 2012 at 9:14 AM, Jesús Gabriel y Galán <jgabrielygalan@gmail.com> wrote:

On Sun, Jul 8, 2012 at 10:13 PM, Joao Silva <lists@ruby-forum.com> wrote:

Brian Candler wrote in post #1067902:

a = [1, 2, 2, 3, 5, 4, 6, 2, 6, 5, 4]
counts = Hash.new(0)
a.each { |val| counts[val] += 1 }
groups = {}
counts.each do |val,count|
  groups[count] ||=
  groups[count] << val
end
groups.each do |count,vals|
  puts "With #{count-1} repeats found #{vals.sort.join(", ")}"
end

One last thing, how do I print the results that I stay in order, because
the above code prints:

With 0 repeats found 1, 3
With 2 repeats found 2
With 1 repeats found 4, 5, 6

and I seek it to print in order:

groups.sort.each do |count,vals|
  puts "With #{count-1} repeats found #{vals.sort.join(", ")}"
end

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/