Skip to content

Instantly share code, notes, and snippets.

@mattdvhope
Last active December 20, 2015 03:49
Show Gist options
  • Save mattdvhope/6066483 to your computer and use it in GitHub Desktop.
Save mattdvhope/6066483 to your computer and use it in GitHub Desktop.
Calculating the array mode
def mode(array)
# I created a new hash to make keys out each integer.
b = Hash.new(0)
# Here, I count/tabulate each time a particular integer appears.
array.each do |value|
b[value] = b[value] + 1
end
# b returns {-2=>1, 1=>3, 2=>3, -5=>2, 3=>1, 4=>1} with the first array
# b returns {18=>1, 2=>2, -5=>4, 3=>2, 10=>1} with the second array
max = []
b.each do |k, v| #e[key,value]
max.push(k) if v == b.values.max
end
max
end
# In its present form, it returns the keys 1, 2 for the first array and -5 for the second array, but I can't convert them into an array.
puts mode([1,2,4,-5,3,-2,1,1,-5,2,2])
puts
puts mode([-5,2,-5,3,-5,3,18,-5,2,10])
@mattdvhope
Copy link
Author

For lines 6-8, it would return a hash like this: {-2=>1, 1=>3, 2=>3, 3=>1, 4=>1}

Question on line 13: How can I say, "If the next value is >= the previous value, then--and only then-- .push ?" If I can figure that out, I hope I can solve this problem. Thanks!

@keithtom
Copy link

I don't think you want to say "If the next value is >= the previous value, then .push ?"
because if the values all came [-2, -1, 0, 1, 2, 3], you'd just push them all.

Of all the frequencies that you have stored in the hash, you only care about the ones that have the highest frequency.

Some examples:

{-2=>1, 1=>3, 2=>3, 3=>1, 4=>1}
You only care about numbers with frequency 3 because 3 is the high frequency. In this case, there happen to be two numbers with a frequency of 3: 1 and 2.

{1 => 1, 2=>1, 3=>1}
The highest frequency is 1. There are 3 numbers with frequency 1: 1, 2, and 3.

So you need to find out what the highest frequency is, then start worrying about how to get those numbers.

@mattdvhope
Copy link
Author

Thanks so much for your help with this so far Tom! My problem (in line 9) is that once I get the hash with these keys and values (including the keys that appear most frequently, i.e., 1 & 2 here), I just can't figure out how to elicit those keys out of the hash (because of the fact that they're the most frequently occurring) and then return them as the array, [1,2]. Is there a method in the Socrates exercises that would do this, or would I need to find one on Ruby docs? I've searched through the docs, but haven't found one yet. As I've Googled, I've briefly read about Hash#each and Enumerable#each_with_index. Would they be of any help here? (I'd been thinking they were beyond the skill/knowledge-level of this exercise at this point.)

@keithtom
Copy link

It sounds like you have the general right idea. You just need to break down your steps until they are easy. If a step is too hard, then you need to break it down more. There may be methods which make things easier for you, but at the end of the day, a hash is just a collection of key/value pairs. There is no secret knowledge/skill about them.

So let's start from line 9, because at that point you have your hash and you know what it looks like.
Let's pretend your hash is {-2=>1, 1=>3, 2=>3, -5=>2, 3=>1, 4=>1}

Let's talk out the steps and make sure you understand exactly why we do each step.

Goal: return an array with the numbers that have the highest frequency (the mode), hence return [1, 2] because the highest frequency is 3.

How do we do this?

Step1: Find the maximum value of the hash
Given the hash above, can you find a way to get the maximum value? There is no 'right' way. Anyway that works is good enough. You mentioned Hash#each. Try using that to find the maximum value. This is its own mini challenge. There are many ways to accomplish this one goal. Reading the docs may help you find other ways to find the maximum value.

Do not think about step 2 at all until you have finished step 1.

Step2: Find all the keys that have a value found in step1 (the maximum value) and return them as an array.
Finding all the keys sounds like you will need to go through each key/value pair again, this time 'picking' or 'selecting' the keys that meet our condition (i.e. you have a value equal to the value from step 1).

Take a few stabs at trying this approach and see if it helps!

@mattdvhope
Copy link
Author

As you instructed, I broke down the problem into these 2 final steps. I found the max values with "b.each do | k, v |", and was thus able to find the respective keys. I'm able to 'puts' of these keys onto successive lines.

I've been Googling for hours trying to find a way to convert puts outputs on successive lines (versus strings on the same line) into an array, but to no avail. I found .split, but that doesn't seem to work for successive lines.

Thanks so much.

@mattdvhope
Copy link
Author

I tried max.push(k) to create an array of the returned keys (of maximum value), but it still only puts them as integers onto successive lines. I tried v.to_s.split, but that didn't work either.

@Ale1
Copy link

Ale1 commented Jul 24, 2013

matt, your method output is already in array form. you are seeing it on your screen as integers in successive lines because you are using "puts" in lines 21-23. (not sure if that was what you were trying to fix).

@keithtom
Copy link

I agree w/ @Ale1. did that help?

@mattdvhope
Copy link
Author

I had it all the time! I guess I should have actually tested it on the exercises!! :-o Thanks so much for your help!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment