RoR array -count identical elements-on including value - ruby-on-rails

how do we count idential values on after appending value in to array
such that
a=[]
a<<1 count of 1 is 1
a<<1 count of 1 is 2
thanks

You could do:
a.select{|v| v == 1}.size
It's only one solution

Someone will probably come up with a more specialized solution, but I would just reduce it
counts = [1,3,3].reduce({}) do |acc,n|
acc.tap do |a|
a[n] ||= 0
a[n] += 1
end
end
counts.each {|k,v| puts "#{k} was found #{v} times"}
(note that tap is ruby 1.9, and is backported in activesupport)
output of that will be
1 was found 1 times
3 was found 2 times

a = [1,2,3,4,5,1,2,2,3,4]
=> [1, 2, 3, 4, 5, 1, 2, 2, 3, 4]
a.uniq.each do |i|
?> puts i.to_s + ' has appeared ' + a.count(i).to_s + ' times'
end
1 has appeared 2 times
2 has appeared 3 times
3 has appeared 2 times
4 has appeared 2 times
5 has appeared 1 times
=> [1, 2, 3, 4, 5]

Related

how to compute year of service

i have this problem
1yr of service 15 days
3yrs of service 17 days
5yrs of service 20 days
10yrs or more of service 25 days
so come up of this code i get the year of employee hired
here's the code
def year_of_service(date_of_hired)
years = [1, 3, 5, 10]
now = Time.now.utc.to_date
get_year = now.year - date_of_hired.year - ((now.month > date_of_hired.month ||
(now.month == date_of_hired.month && now.day >= date_of_hired.day)) ? 0 : 1)
end
my solution here is i will use if statements but for me it will be a long code is there another solution that make it short or other possble solution
the difficulties is here how can i know if the 'get_year' is between of my array???
example:
the 'get_year' is 4 how can know that is 3 years of service not 5 but 4 is not in the array
You may employ take_while or select.
y = [1, 3, 5, 10]
y.take_while { |i| i <= 4 }.max #=> 3
y.select { |i| i <= 4 }.last #=> 3
But these involve collecting more elements than needed. Another approach is to find the index of the last element matching your criteria, then use regular array-notation to grab that element:
y[y.rindex { |i| i <= 4 }] #=> 3
You could also use find, but that would involve reversing the array first. Currently there is no rfind in Ruby.

ruby arrays count of most frequent element [duplicate]

This question already has answers here:
How to find an item in array which has the most occurrences [duplicate]
(11 answers)
Closed 6 years ago.
I'm trying to figure out how to find a count of the most frequent element in an array of integers. I can think of a few methods that might be helpful but when I get to writing an expression inside the block I get complete lost on how to compare an element with the next and previous element. Any ideas? All help is really really appreciated!!!
An easy was is to determine all the unique values, convert each to its count in the array, then determine the largest count.
def max_count(arr)
arr.uniq.map { |n| arr.count(n) }.max
end
For example:
arr = [1,2,4,3,2,6,3,4,2]
max_count(arr)
#=> 3
There are three steps:
a = arr.uniq
#=> [1, 2, 4, 3, 6]
b = a.map { |n| arr.count(n) }
#=> [1, 3, 2, 2, 1]
b.max
#=> 3
A somewhat more efficient way (because the elements of arr are enumerated only once) is to use a counting hash:
def max_count(arr)
arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }.values.max
end
max_count(arr)
#=> 3
We have:
a = arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
#=> {1=>1, 2=>3, 4=>2, 3=>2, 6=>1}
b = a.values
#=> [1, 3, 2, 2, 1]
b.max
#=> 3
See Hash::new for an explanation of Hash.new(0). Briefly, if h = Hash.new(0) and h does not have a key k, h[k] will return the default value, which here is zero. h[k] += 1 expands to h[k] = h[k] + 1, so if h does not have a key k, this becomes h[k] = 0 + 1. On the other hand, if, say, h[k] => 2, then h[k] = h[k] + 1 #=> h[k] = 3 + 1.

What's a good way to create a string array in Ruby based on integer variables?

The integer variables are:
toonie = 2, loonie = 1, quarter = 1, dime = 0, nickel = 1, penny = 3
I want the final output to be
"2 toonies, 1 loonie, 1 quarter, 1 nickel, 3 pennies"
Is there a way to interpolate this all from Ruby code inside [] array brackets and then add .join(", ")?
Or will I have to declare an empty array first, and then write some Ruby code to add to the array if the integer variable is greater than 0?
I would do something like this:
coins = { toonie: 2, loonie: 1, quarter: 1, dime: 0, nickel: 1, penny: 3 }
coins.map { |k, v| pluralize(v, k) if v > 0 }.compact.join(', ')
#=> "2 toonie, 1 loonie, 1 quarter, 1 nickel, 3 penny"
Note that pluralize is a ActionView::Helpers::TextHelper method. Therefore it is only available in views and helpers.
When you want to use your example outside of views, you might want to use pluralize from ActiveSupport instead - what makes the solution slightly longer:
coins.map { |k, v| "#{v} #{v == 1 ? k : k.pluralize}" if v > 0 }.compact.join(', ')
#=> "2 toonie, 1 loonie, 1 quarter, 1 nickel, 3 penny"
Can be done in rails:
hash = {
"toonie" => 2,
"loonie" => 1,
"quarter" => 1,
"dime" => 0,
"nickel" => 1,
"penny" => 3
}
hash.to_a.map { |ele| "#{ele.last} #{ele.last> 1 ? ele.first.pluralize : ele.first}" }.join(", ")
Basically what you do is convert the hash to an array, which will look like this:
[["toonie", 2], ["loonie", 1], ["quarter", 1], ["dime", 0], ["nickel", 1], ["penny", 3]]
Then you map each element to the function provided, which takes the inner array, takes the numeric value in the last entry, places it in a string and then adds the plural or singular value based on the numeric value you just checked. And finally merge it all together
=> "2 toonies, 1 loonie, 1 quarter, 1 nickel, 3 pennies"
I'm not sure what exactly you're looking for, but I would start with a hash like:
coins = {"toonie" => 2, "loonie" => 1, "quarter" => 1, "dime" => 0, "nickel" => 1, "penny" => 3}
then you can use this to print the counts
def coin_counts(coins)
(coins.keys.select { |coin| coins[coin] > 0}.map {|coin| coins[coin].to_s + " " + coin}).join(", ")
end
If you would like appropriate pluralizing, you can do the following:
include ActionView::Helpers::TextHelper
def coin_counts(coins)
(coins.keys.select { |coin| coins[coin] > 0}.map {|coin| pluralize(coins[coin], coin)}).join(", ")
end
This is just for fun and should not be used in production but you can achieve it like
def run
toonie = 2
loonie = 1
quarter = 1
dime = 0
nickel = 1
penny = 3
Kernel::local_variables.each_with_object([]) { |var, array|
next if eval(var.to_s).to_i.zero?
array << "#{eval(var.to_s)} #{var}"
}.join(', ')
end
run # returns "2 toonie, 1 loonie, 1 quarter, 1 nickel, 3 penny"
The above does not implement the pluralization requirement because it really depends if you will have irregular plural nouns or whatever.
I would go with a hash solution as described in the other answers

Select method with args separated by double-pipes only checking first element... Alternative?

I have a bit of broken legacy code I have to fix. Its purpose was to take a large array and return elements that have a particular sector number.
Here's a simplified version of the code in the app. Goal: return any instance of 1 or 3 in array:
array = [1,1,2,2,3,3].select{|num| num == (1 || 3) }
But the return value is simply #=> [1, 1] when the desired return was #=> [1, 1, 3, 3]
Basically, what I'm looking for is the Ruby equivalent to the following SQL query:
SELECT num FROM array
WHERE num IN (1, 3);
Ruby 1.8.7, Rails 2.3.15
Do as below to meet your need :
array = [1,1,2,2,3,3]
array.select{|num| [1,3].include? num }
# => [1, 1, 3, 3]
See why you got only [1,1].
1 || 3 # => 1
1 || 3 will always returns 1, thus num == 1 is evaluated as true when select is passing only 1. As a result you got [1,1].

Splitting/Slicing array in ruby

I've found this similar two questions to the one I'm about to ask:
Split array up into n-groups of m size?
and
Need to split arrays to sub arrays of specified size in Ruby
This splits array into three arrays with each array having three elements :
a.each_slice(3) do |x,y,z|
p [x,y,z]
end
So if I do this (my array size is 1000) :
a.each_slice(200) do |a,b,c,d,e|
p "#{a} #{b} #{c} #{d} #{e}"
end
This should split my array into 5 arrays each having 200 members? But it doesn't?
What I actually need to do is to put 200 random elements into 5 arrays, am I on the right track here, how can I do this?
Enumerable#each_slice
If you provide a single argument to the block of each_slice then it will fill that argument with an array of values less than or equal to the given argument. On the last iteration if there are less than n values left then the array size will be whatever is left.
If you provide multiple arguments to the block of each_slice then it will fill those values with the values from the source array. If the slice size is greater than the number of arguments given then some values will be ignored. If it is less than the number of arguments than the excess arguments will be nil.
a = (1..9).to_a
a.each_slice(3) {|b| puts b.inspect }
[1,2,3]
[4,5,6]
[7,8,9]
a.each_slice(4) {|b| puts b.inspect }
[1,2,3,4]
[5,6,7,8]
[9]
a.each_slice(3) {|b,c,d| puts (b + c + d)}
6 # 1 + 2 + 3
15 # 4 + 5 + 6
24 # 7 + 8 + 9
a.each_slice(3) {|b,c| puts (b + c)}
3 # 1 + 2, skips 3
9 # 4 + 5, skips 6
15 # 7 + 8, skips 9
a.each_slice(2) {|b,c| puts c.inspect}
2
4
6
8
nil
a.each_slice(3) {|b,c,d,e| puts e.inspect}
nil
nil
nil
irb(main):001:0> a= (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):002:0> a.sample(3)
=> [5, 10, 1]
irb(main):003:0> (1..3).map{ a.sample(3) }
=> [[6, 2, 5], [8, 7, 3], [4, 5, 7]]
irb(main):004:0>
Actually you will return a string with the five elements inserted in it.
You can try something:
a1 = [], a2 = [], a3 = [], a4 = [], a5 = []
a.each_slice(5) do |a,b,c,d,e|
a1 << a
a2 << b
a3 << c
a4 << d
a5 << e
end
You will end up with five arrays containing 200 elements each.
I used the simplest possible syntax to make it clear, you can
make it much more condensed.
If you want to assign that result to 5 different arrays, you could use the splat operator,like this:
a,b,c,d,e = *(1..1000).each_slice(200).to_a

Resources