1

Is it possible to create an Array from another Array?
Lang: Ruby on Rails

Case

Workers are entitled to fill in their own work hours. Sometimes they forget to do it. This is what I want to tackle. In the end, I want an Array with time codes of periods the worker forgot to register his hours.

timecodes = [201201, 201202, 201203, 201204, 201205, 201206, 201207, 201208, 201209, 201210, 201211, 201212, 201213, 201301, 201302, 201304, 201305, 201306, ...]

Worker works from 201203 to 201209 with us.

timecards = [201203, 201204, 201205, 201207, 201208, 201209]

As you see, he forgot to register 201206.

What I want to do

# Create Array from timecode on start to timecode on end
worked_with_us = [201203, 201204, 201205, 201206, 201207, 201208, 201209]  
   #=> This is the actual problem, how can I automate this?

forgot_to_register = worked_with_us.?????(timecards)
forgot_to_register = worked_with_us - timecards  # Thanks Zwippie
   #=> [201206]

Now I know which period the worker forgot to register his hours.

All together

  1. How can I create an Array from another Array, giving a start and end value?

1 Answer 1

2

You can just subtract arrays with - (minus):

[1, 2, 3] - [1, 3] = [2]

To build an array with years/months, this can be done with a Range, but this only works if you build an array for each year, something like:

months = (2012..2013).map do |year|
  ("#{year}01".."#{year}12").to_a.collect(&:to_i)
end.flatten

  => [201201, 201202, 201203, 201204, 201205, 201206, 201207, 201208, 201209, 201210, 201211, 201212, 201301, 201302, 201303, 201304, 201305, 201306, 201307, 201308, 201309, 201310, 201311, 201312]

And for the function to create those ranges dynamically:

def month_array(year_from, year_to, month_from=1, month_to=12)
  (year_from..year_to).map do |year|
    # Correct from/to months
    mf = year_from == year ? month_from : 1
    mt = year_to == year ? month_to : 12

    (mf..mt).map do |month|
      ("%d%02d" % [year, month]).to_i
    end
  end.flatten
end

Update: You wanted other input parameters for this method, but I hope you can work that out yourself. :)

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, I was totally thinking to complicated! Do you have any ideas on the first issue?
Thank you, I achieved that with (2012..2013).each do |y| { (1..13).each do |p| { timecodes.push "#{y}#{"02d" % p}" } }. I want to create an array based on this array. So I can give the start value and the stop value and create an array from those. Let's say: start = 201210, stop = 201303. The Array should be: worked_with_us = [201210, 201211, 201212, 201213, 201301, 201302, 201303]
Ok, I added a method to do that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.