I was attempting to find a mode without using a hash, but now do not know if its possible, so I am wondering if someone can help me to translate my near working array code, into hash mode to make it work.

I have seen a shorter solution which I will post, but I do not quite follow it, I'm hoping this translation will help me to understand a hash better.

Here is my code, with my comments - I have bolded the part that I know will not work, as I'm comparing a frequency value, to the value of an element itself

@new = [0] 

def mode(arr)
    arr.each do |x|                                                 #do each element in the array
    freq = arr.count(x)                                             #set freq equal to the result of the count of each element

    if freq > @new[0] && @new.include?(x) == false                  #if **frequency of element is greater than the frequency of the first element in @new array** and is not already there
        @new.unshift(x)                                             #send that element to the front of the array
        @new.pop                                                    #and get rid of the element at the end(which was the former most frequent element)
    elsif freq == @new[0] && @new.include?(x) == false              #else **if frequency of element is equal to the frequency of the first element in @new array** and is not already there
        @new << x                                                   #send that element to @new array
    end
end

if @new.length > 1                                                  #if @new array has multiple elements
    @new.inject(:+)/@new.length.to_f                                #find the average of the elements
end

@new                                                                #return the final value
end

mode([2,2,6,9,9,15,15,15])
mode([2,2,2,3,3,3,4,5])

Now I have read this post: Ruby: How to find item in array which has the most occurrences?

And looked at this code

arr = [1, 1, 1, 2, 3]
freq = arr.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
arr.sort_by { |v| freq[v] }.last

But I dont quite understand it.

What I'd like my code to do, is, as it finds the most frequent element,
to store that element as a key, and its frequency as its value.
And then I'd like to compare the next elements frequency to the frequency of the existing pair,
and if it is equal to the most frequent, store it as well,
if it is greater, replace the existing,
and if it is less than, to disregard and move to the next element.

Then of course, I'd like to return the element which has most frequencies, not the amount of frequencies,
and if two or more elements share the most frequencies, then to find the average of those numbers.

I'd love to see it with some hint of my array attempt, and maybe an explanation of that hash method that I posted above, or one that is broken down a little more simply.

有帮助吗?

解决方案

This seems to fit your requirements:

def mode(array)
  histogram = array.each_with_object(Hash.new(0)) do |element, histogram|
    histogram[element] += 1
  end
  most_frequent = histogram.delete_if do |element, frequency|
    frequency < histogram.values.max
  end
  most_frequent.keys.reduce(&:+) / most_frequent.size.to_f
end

It creates a hash of frequencies histogram, where the keys are the elements of the input array and the values are the frequency of that element in the array. Then, it removes all but the most frequent elements. Finally, it averages the remaining keys.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top