Home > Enterprise >  How to combine a large number of hashes into a sorted single Array of Hashes?
How to combine a large number of hashes into a sorted single Array of Hashes?

Time:01-19

I have a generated a collection of hashes from an Excel Spreadsheet, containing users arranged by their assigned 'level' number.

user_data = 

         {"1st Level"=>"[email protected]", "2nd Level"=>"[email protected]", "3rd Level"=>"[email protected]"}.
         {"1st Level"=>"[email protected]", "2nd Level"=>"[email protected]", "3rd Level"=>"[email protected]"}.
         {"1st Level"=>"[email protected]", "2nd Level"=>"nil", "3rd Level"=>"[email protected]"}.
         {"1st Level"=>"[email protected]", "2nd Level"=>"[email protected]", "3rd Level"=>"[email protected]"}

I'm attempting to instead have the data displayed as below, in a single Array of hashes, sorted via the Level Key, and with any K:V Pair containing a Nil Value removed. however I'm struggling to figure out how this is best done with a collection of hashes, any advice appreciated:

new_data = 
[
     { "1st Level"=>"[email protected]"},
     { "1st Level"=>"[email protected]"}
     { "1st Level"=>"[email protected]"},
    
     { "2nd Level"=>"[email protected]"},
     { "2nd Level"=>"[email protected]"}
     { "2nd Level"=>"[email protected]"},

     { "3rd Level"=>"[email protected]"},
     { "3rd Level"=>"[email protected]"}
     { "3rd Level"=>"[email protected]"},
]

EDIT with context:

def generate_list
    data = Roo::Spreadsheet.open('test.file') 
    headers = data.row(1)
    
    data.each_with_index do |row, idx|
      next if idx.zero? 
    
      user_data = Hash[[headers, row].transpose]
      puts user_data.compact
end

CodePudding user response:

how about something like this:

def generate_list
    data = Roo::Spreadsheet.open('test.file') 
    headers = data.row(1)
    user_data = {}
    data.each_with_index do |row, idx|
      next if idx.zero? 
      headers.each_with_index do |header, idx2|
        user_data[header] ||= []
        user_data[header] << row[idx2] unless row[idx2].nil?
      end
    end
    user_data
end

which should make something like:

new_data = 
{
     "1st Level"=> ["[email protected]","[email protected]","[email protected]"],
     "2nd Level"=> ["[email protected]","[email protected]","[email protected]"],
     "3rd Level"=> ["[email protected]","[email protected]","[email protected]"],
}

CodePudding user response:

Given the following data:

user_data = [
  {"1st Level"=>"[email protected]", "2nd Level"=>"[email protected]", "3rd Level"=>"[email protected]"},
  {"1st Level"=>"[email protected]", "2nd Level"=>"[email protected]", "3rd Level"=>"[email protected]"},
  {"1st Level"=>"[email protected]", "2nd Level"=>nil, "3rd Level"=>"[email protected]"},
  {"1st Level"=>"[email protected]", "2nd Level"=>"[email protected]", "3rd Level"=>"[email protected]"}
]

We can apply this transformation:

new_data = user_data.flat_map do |element|
  element.compact.map { |level, email| { level => email } }
end

To get the result you described:

new_data = [
  {"1st Level"=>"[email protected]"},
  {"2nd Level"=>"[email protected]"},
  {"3rd Level"=>"[email protected]"},
  {"1st Level"=>"[email protected]"},
  {"2nd Level"=>"[email protected]"},
  {"3rd Level"=>"[email protected]"},
  {"1st Level"=>"[email protected]"},
  {"3rd Level"=>"[email protected]"},
  {"1st Level"=>"[email protected]"},
  {"2nd Level"=>"[email protected]"},
  {"3rd Level"=>"[email protected]"}
]
  •  Tags:  
  • Related