2014-09-16 3 views
1

У меня есть 2 массива одного массива хэшей другого массива ключей. Мне нужно сделать массив хешей в том же порядке, что и массив ключей. Как я могу это сделатьЗаказать массив хэшей другим массивом

header = ["header1", "header2", "header3", "header4", "header5"] 
record = [{"header4" =>"value4"}, {"header3" =>"value3"}, {"header5"=>"value5"}, {"header1"=>"value1"}, {"header2"=>"value2"}] 

мне нужно запись массива положить в том же порядке, как массив заголовке

record = [{"header1" =>"value1"}, {"header2" =>"value2"}, {"header3"=>"value3"}, {"header4"=>"value4"}, {"header5"=>"value5"}] 

большое спасибо каждому за помощь. Я хочу добавить еще один вопрос к этому сообщению. Я пытаюсь использовать методы, предложенные ниже, для создания CSV-документа из базы данных. Поэтому я хочу, чтобы организовать столбцы в определенном порядке и у меня есть шаблон этого порядка и этот шаблон хранится в виде массива заголовков, но когда я делаю

csv<< mymodel.attributes.values.sort_by! { |h| header.index(h.keys[0]) 

Это не работает

+0

Пожалуйста, обратитесь к последующей вопрос в новом StackOverflow вопрос. Примите ответ ниже для вашего первоначального вопроса. –

ответ

5

Array#sort_by!/Enumerable#sort_by принимает блок. Для сравнения используется возвращаемое значение блока. Для вашего случая вы можете использовать Array#index.

header = ["header1", "header2", "header3", "header4", "header5"] 
record = [{"header4" =>"value4"}, {"header3" =>"value3"}, 
      {"header5"=>"value5"}, {"header1"=>"value1"}, 
      {"header2"=>"value2"}] 
record.sort_by! { |h| header.index(h.keys[0]) } 
# => [{"header1"=>"value1"}, {"header2"=>"value2"}, {"header3"=>"value3"}, 
#  {"header4"=>"value4"}, {"header5"=>"value5"}] 
+0

Nice one, ft ... –

0

Для этого простого объекта, который вы на самом деле не нужен дополнительный массив, как это будет работать

record.sort_by do |hash| 
    hash.keys.find{|key| key=~ /header/}.scan(/\d+/).pop.to_i 
end 
#=> [{"header1"=>"value1"}, {"header2"=>"value2"}, {"header3"=>"value3"}, {"header4"=>"value4"}, {"header5"=>"value5"}] 

У меня есть чувство, хотя, что этот вопрос был лишен вплоть до предметов первой необходимости, но думал, что показать вы все равно. Так как вы просто хотите отсортировать по номеру заголовка, это найдет заголовочный ключ, тогда scan для чисел выскочит последним и преобразуется в Integer для сортировки. поэтому он будет работать для любого Hash с ключами, как "header1" или "header1432"

1

Я хотел бы сделать это как @falsetru сделал, но вот еще один способ:

record.each_with_object({}) { |h,g| g[h.keys.first] = h }.values_at(*header) 
    #=> [{"header1"=>"value1"}, {"header2"=>"value2"}, {"header3"=>"value3"}, 
    # {"header4"=>"value4"}, {"header5"=>"value5"}] 
+0

очень приятно. Логика немного запутанна в отношении читаемости (не ваша вина вообще), но краткость прекрасна. Хотя я бы использовал 'keys.find {| k | k = ~/header /} 'вместо' .first', если ключи не сортируются в этом порядке в каждом 'Hash'. – engineersmnky

+0

@engineersmnky, я согласен с вашей читабельностью, что является основной причиной, по которой я предпочитаю использовать 'sort_by',' index'. –

0

Вышеуказанные ответы все замечательно, но ни один не выполнять работа в O (n) времени. Я думаю, что теоретическая производительность и ясность может быть улучшена путем поворота results во временную хеш:

>> record_h = record.reduce(:merge) 
=> {"header4"=>"value4", "header3"=>"value3", "header5"=>"value5", "header1"=>"value1", "header2"=>"value2"} 

-

>> header.map{|h| {h => record_h[h]}} 
=> [{"header1"=>"value1"}, {"header2"=>"value2"}, {"header3"=>"value3"}, {"header4"=>"value4"}, {"header5"=>"value5"}] 
Смежные вопросы