Ruby: передача ключа / значения после преобразования объектов в массив

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

6
задан endex 13 July 2018 в 17:35
поделиться

5 ответов

Так как :foo уникальна для :id. Вы можете сделать это следующим образом:

data.group_by {|h| h[:id]}.map do |_,sa| 
  sa.map(&:dup).sort_by {|h| h.delete(:sort) }.reduce do |m,h| 
     m.merge(h) {|key,old,new| key == :content ? old + new : old } 
  end.tap {|h| h[:concated_value] = h.delete(:content) }
end  
#=> [
# {"id":14, foo: "2022", "concated_value":"9105"},
# {"id":15, foo: "2888", "concated_value":"3134"},
# {"id":16, foo: "3112", "concated_value":"8449"}
# ]
  • Сначала мы группируем по id. group_by {|h| h[:id]}
  • Затем мы дублируем хеши в группах (чтобы не уничтожить оригинал). map(&:dup)
  • Затем мы сортируем сортировку и удаляем ее одновременно. .sort_by {|h| h.delete(:sort) }
  • Затем мы объединяем группы и объединяем только контентный ключ. m.merge(h) {|key,old,new| key == :content ? old + new : old }
  • Затем мы просто меняем ключ для content на concated_value tap {|h| h[:concated_value] = h.delete(:content) }
4
ответ дан engineersmnky 17 August 2018 в 12:20
поделиться
  • 1
    Большое спасибо за подробное объяснение! Еще один вопрос. Скажем, я хотел использовать reject для некоторых элементов из :content, где .length > 1. Будет ли это работать в этой ситуации? – endex 13 July 2018 в 19:05
  • 2
    Конечно, просто отклоняйте их от data.reject {|h| h[:content].length > 1 }.group_by#... – engineersmnky 13 July 2018 в 19:08
data.sort_by { |h| h[:sort] }.
     each_with_object({}) do |g,h| h.update(g[:id]=>{ id: g[:id],
       concatenated_value: g[:content].to_s, foo: g[:foo] }) {  |_,o,n|
         o.merge(concatenated_value: o[:concatenated_value]+n[:concatenated_value]) }
     end.values
  #=> [{:id=>14, :concatenated_value=>"9105", :foo=>"2022"},
  #    {:id=>15, :concatenated_value=>"3134", :foo=>"2888"},
  #    {:id=>16, :concatenated_value=>"8449", :foo=>"3112"}]

Используется форма Hash # update (aka merge!), в которой используется блок для определения значений ключей (здесь значение :id), которые присутствуют в оба хеша объединяются. См. Документ для описания трех переменных блока (здесь _, o и n).

Обратите внимание, что приемник values (в конце) следующий.

{ 14=>{ :id=>14, :concatenated_value=>"9105", :foo=>"2022" },
  15=>{ :id=>15, :concatenated_value=>"3134", :foo=>"2888" },
  16=>{ :id=>16, :concatenated_value=>"8449", :foo=>"3112" } } 
-1
ответ дан Cary Swoveland 17 August 2018 в 12:20
поделиться

Мы можем использовать первое значение из value_array, чтобы получить наш: id & amp; : foo values ​​

formatted = data.group_by { |d| d[:id]}.values.map do |value_array|
  concated_value = value_array.sort_by { |b| b[:sort] }
                              .map     { |c| c[:content] }.join
  value_array.first.slice(:id, :foo)
             .merge concated_value: concated_value
end
1
ответ дан Mobile Perpetuum 17 August 2018 в 12:20
поделиться

Это будет работать даже без Rails:

$irb> formatted = []
$irb> data.sort_by!{|a| a[:sort]}.map {|z| z[:id]}.uniq.each_with_index { |id, index| formatted << {id: id, concated_value: data.map{|c| (c[:id] == id ? c[:content] : nil)}.join, foo: data[index][:foo]}}
$irb> formatted
[{:id=>14, :concated_value=>"9105", :foo=>"2022"}, 
{:id=>15, :concated_value=>"3134", :foo=>"2888"},
{:id=>16, :concated_value=>"8449", :foo=>"3112"}]
1
ответ дан NM Pennypacker 17 August 2018 в 12:20
поделиться

Я думаю, что это хорошая утилита для reduce, так как после группировки вам нужно сначала избавиться от ID в результирующем [ID, VALUES] массиве от group_by и просто вернуть уменьшенную версию VALUES части - все это можно сделать без каких-либо зависимостей ActiveSupport и т. д.:

data
  .group_by{ |d| d[:id] } # Get an array of [ID, [VALUES]]
  .reduce([]) do |a, v| # Reduce it into a new empty array
    # Append a new hash to the new array
    a << {
      id: v[1].first[:id], # Just take the ID of the first entry
      foo: v[1].first[:foo], # Dito for foo
      concatenated: v[1] 
        .sort_by{ |s| s[:sort] } # now sort all hashes by its sort key
        .collect{ |s| s[:content] } # collect the content
        .join # and merge it into a string
    }
  end

Выход:

[{:id=>14, :foo=>"2022", :concatenated=>"9105"}, 
 {:id=>15, :foo=>"2888", :concatenated=>"3134"}, 
 {:id=>16, :foo=>"3112", :concatenated=>"8449"}]

EDIT

У меня был другой подход в виду, когда я начал писать предыдущее решение, reduce не было действительно необходимо, так как размер массива после group_by не изменяется, поэтому достаточно map.

Но пока переписывая код, я думал, что создание нового хэша со всеми ключами и копирование всех значений из первого хэша в VALUES было слишком большим, поэтому было бы проще просто отказаться от служебных клавиш:

keys_to_ignore = [:sort, :content]

data
  .group_by{ |d| d[:id] } # Get an array of [ID, [VALUES]]
  .map do |v| 
    v[1]
      .first # Take the first hash from [VALUES]
      .merge({'concatenated': v[1] # Insert the concatenated values
        .sort_by{ |s| s[:sort] } # now sort all hashes by its sort key
        .collect{ |s| s[:content] } # collect the content
        .join # and merge it into a string
      })
      .select { |k, _| !keys_to_ignore.include? k }
  end

Выход

[{:id=>14, :foo=>"2022", :concatenated=>"9105"}, 
 {:id=>15, :foo=>"2888", :concatenated=>"3134"}, 
 {:id=>16, :foo=>"3112", :concatenated=>"8449"}]

Демо-версия здесь

2
ответ дан wiesion 17 August 2018 в 12:20
поделиться
  • 1
    Это супер чисто, любите. Спасибо, что показал мне collect – endex 13 July 2018 в 19:28
  • 2
    reduce не было необходимости, map было бы достаточным - я также добавил еще один подход к решению этого вопроса, если бы было больше значений для возврата из исходных хэшей. – wiesion 13 July 2018 в 19:53
Другие вопросы по тегам:

Похожие вопросы: