0

I have a store which holds objects like [obj1, obj2, obj3] with attributes date, task, staff, etc. The objects contains data like date "18.07.2019", staff 1001, task 1

My initial idea was to group them somehow, but I miserably failed. I'd like build a structure as shown at the bottom of the post, either from the objects itselves or from an contructed array holding only three (or maybe more) attributes.

Challenge:

As I am using an very old ruby 1.6 I can't use all the modern easy methods.

The store consists of objects like [obj1, obj2, obj3] with attributes date, task, staff.

    all_items = []
    store.each do |obj|
      all_items << [obj.date, obj.task, obj.staff]
    end

My attempt:

I tried a lot like

    h = {}
    h[date] = []
    h[date] << [obj.date, obj.task, obj.staff]
    h[date].to_h

Current state:

    h = {}
    all_items = []
    store.each do |obj|
      h[obj.date.to_s] = []
      h[obj.date.to_s] << { obj.date.to_s => [obj.staff, obj.task] }
      all_items << Hash[*h[obj.date.to_s].flatten]
    end
    puts all_items.inspect

looks like this (still nothing I can work with):

[ 
  {"18.07.2019"=>[1001, 2]}, 
  {"18.07.2019"=>[1001, 2]}, 
  {"18.07.2019"=>[1001, 3]}, 
  {"19.07.2019"=>[1001, 1]}, 
  {"20.07.2019"=>[1002, 3]},
  ...
]

Expected format:

I would love to come out with something like this, so that I know who has which tasks on which date in order to work with the data later in my program.

{
  "18.07.2019" => [
    { staff: 1001, tasks: [1, 2, 3]},
    { staff: 1002, tasks: [1, 2, 4]}
  ],
  "19.07.2019" => [
    { staff: 1001, tasks: [2, 3]},
    { staff: 1002, tasks: [1, 2]}
  ],
  ...
}
6
  • What's the input data? Commented Aug 7, 2019 at 19:40
  • Updated the beginning of my question, the store consists of objects like [obj1, obj2, obj3] with attributes date, task, staff, etc. Commented Aug 7, 2019 at 19:42
  • 1
    You can add an example of your input data. I'm not gonna tell anybody how your data looks like. Commented Aug 7, 2019 at 19:44
  • I am using an external SDK an get objects back as described. Not sure if the input data is really relevant. I can only access certain methods of the objects as described. Do you expect a class and some methods? Commented Aug 7, 2019 at 19:47
  • No, if your expected output is like in the answer, there should be a "18.07.2019", 1001, [1,2,3], ... in somewhere. Commented Aug 7, 2019 at 19:50

1 Answer 1

1

Unfortunately, I don't have an actual Ruby 1.6 available since its last update was releases in 2002 and it doesn't compile on any modern system anymore. As such, I wasn't able to test if this code actually works on this Ruby version.

Still, you should be able to get your desired result with something like this:

result = {}
store.each do |obj|
  date = obj.date.to_s
  staff = obj.staff
  task = obj.task

  # An Array of Hashes for each date in the result hash
  result[date] ||= []

  # Find an existing Hash for the current staff id
  staff_obj = result[date].find { |hash| hash[:staff] == staff }

  # If we don't have a Hash for the current staff id yet, create a new one
  # and add it to the result Hash
  unless staff_obj
    staff_obj = { :staff => staff, :tasks => [] }
    result[date] << staff_obj
  end

  # Finally, we add the current task id to the list of tasks for
  # the current date and staff
  staff_obj[:tasks] << task
end

puts result.inspect

Note that this can be rather inefficient to create your desired data structure if there are a lot of different staff ids since we have to find the existing hash for the date and staff in each loop. This could be improved by using a different result structure such as:

{
  "18.07.2019" => {
    1001 => [1, 2, 3],
    1002 => [1, 2, 4]
  },
  "19.07.2019" => {
    1001 => [2, 3],
    1002 => [1, 2]
  },
  ...
}

To create this structure, you could use this simplified approach which should be quite efficient:

result = {}
store.each do |obj|
  date = obj.date.to_s
  staff = obj.staff
  task = obj.task

  result[date] ||= {}
  result[date][staff] ||= []
  result[date][staff] << task
end
Sign up to request clarification or add additional context in comments.

3 Comments

Reads easy, I'll give it a go. Nice alternative approach. ||= is nice, Really appreciated!
Don't ask why I use this old version :D
Works perfectly fine!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.