Как удалить дополнительный уровень массива со значением nil из возвращенного массива - PullRequest
0 голосов
/ 23 октября 2018

У меня есть этот код, который почти дает мне то, что я хочу.

def merge_data(keys, data)

merged_data = keys.map {|hash| data.first.map {|k,v| if hash.values.first == k then hash.merge(v) end}}

end

Ниже приведена разница между ожидаемым (первым) и фактическим возвращаемым значением:

-[{:awesomeness=>10,
   -  :first_name=>"blake",
   -  :height=>"74",
   -  :last_name=>"johnson"},
   - {:awesomeness=>9, :first_name=>"ashley", :height=>60, :last_name=>"dubs"}]

   +[[{:awesomeness=>10,
   +   :first_name=>"blake",
   +   :height=>"74",
   +   :last_name=>"johnson"},
   +  nil],
   + [nil,
   +  {:awesomeness=>9, :first_name=>"ashley", :height=>60, :last_name=>"dubs"}]]

Если кто-нибудь может объяснить, почему я получаю дополнительный уровень массива с индексомиз ноля это будет высоко ценится!

Основано на следующих данных:

let(:keys) {[
       {:first_name => "blake"},
       {:first_name => "ashley"}
]}

  let(:data) {[
       {"blake" => {
            :awesomeness => 10,
                 :height => "74",
              :last_name => "johnson"},
        "ashley" => {
            :awesomeness => 9,
                 :height => 60,
              :last_name => "dubs"}
    }
 ]}

  let(:merged_data) {[
       {:first_name => "blake",
        :awesomeness => 10,
             :height => "74",
          :last_name => "johnson"},

       {:first_name => "ashley",
        :awesomeness => 9,
             :height => 60,
          :last_name => "dubs"}
]}

Спасибо!

Ответы [ 3 ]

0 голосов
/ 23 октября 2018

Учитывая набор данных:

data = {
        "blake" => {
            :awesomeness => 10,
                 :height => "74",
              :last_name => "johnson"},
        "ashley" => {
            :awesomeness => 9,
                 :height => 60,
              :last_name => "dubs"}
        }

Почему бы просто не так?

data.map { |h| h.last.merge({first_name: h.first}) }

#=> [{:awesomeness=>10, :height=>"74", :last_name=>"johnson", :first_name=>"blake"}, {:awesomeness=>9, :height=>60, :last_name=>"dubs", :first_name=>"ashley"}]


Редактировать

Итак,если я хорошо понимаю вашу структуру данных, попробуйте Enumerable # each_with_object :

def merge_data(keys, data)
  keys.each_with_object([]) { |hash, obj| data.first.map { |k,v| if hash.values.first == k then obj << hash.merge(v) end } }
end

keys = [
         {:first_name => "blake"},
         {:first_name => "ashley"}
       ]

data = [{
        "blake" => {
            :awesomeness => 10,
            :height => "74",
            :last_name => "johnson"},
        "ashley" => {
            :awesomeness => 9,
            :height => 60,
            :last_name => "dubs"}
        }]

merge_data(keys, data)

#=> [{:first_name=>"blake", :awesomeness=>10, :height=>"74", :last_name=>"johnson"}, {:first_name=>"ashley", :awesomeness=>9, :height=>60, :last_name=>"dubs"}]
0 голосов
/ 23 октября 2018
keys = [{ :first_name=> "ashley" }, { :first_name=>"blake" }]    
data = [{ "blake"  => { :awesomeness=>10, :height=>"74", :last_name=>"johnson" },
          "margo"  => { :awesomeness=>30, :height=>"63", :last_name=>"magpie"  },
          "ashley" => { :awesomeness=>9,  :height=>"60", :last_name=>"dubs"    } }]

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

data_adj = data.reduce(&:merge)
   #=> {"blake" =>{:awesomeness=>10, :height=>"74", :last_name=>"johnson"},
   #    "margo" =>{:awesomeness=>30, :height=>"63", :last_name=>"magpie"},
   #    "ashley"=>{:awesomeness=>9,  :height=>"60", :last_name=>"dubs"}}

Второй - объединение хешей в keys с соответствующими значениями * 1007.*:

keys.map { |h| h.merge(data_adj[h[:first_name]]) }
  #=> [{:first_name=>"ashley", :awesomeness=>9,  :height=>"60", :last_name=>"dubs"},
  #    {:first_name=>"blake",  :awesomeness=>10, :height=>"74", :last_name=>"johnson"}]

Этот подход был бы особенно эффективен, если бы операция объединения выполнялась многократно, для различных значений keys, поскольку data_adj нужно вычислять только один раз.Деление задачи на две части также тестирование скорости.

0 голосов
/ 23 октября 2018

Ты почти у цели, просто нужна была тонкая настройка:

def merge_data(keys, data)
  merged_data = keys.map {|hash| data.first.map {|k,v| if hash.values.first == k then hash.merge(v) end }.compact[0] }
end

keys = [{:first_name => "blake"}, {:first_name => "ashley"}]

data = [
  {"blake" => {
       :awesomeness => 10,
            :height => "74",
         :last_name => "johnson"},
   "ashley" => {
       :awesomeness => 9,
            :height => 60,
         :last_name => "dubs"}
  }]

puts  merge_data(keys, data).inspect

#=>
[ 
  {
    :first_name=>"blake",
    :awesomeness=>10,
    :height=>"74",
    :last_name=>"johnson"},
  {
    :first_name=>"ashley",
    :awesomeness=>9,
    :height=>60,
    :last_name=>"dubs"
  }
]

Что изменилось ??

Добавлено .compact[0] во внутренний блок.

Почему?Потому что это map, работающий на каждом ключе и каждом значении данных.Возвращая nil для одного, который не совпадает с другим, и возвращая массив каждый раз вместо Hash объекта.

Однако мы можем создать собственный класс и восстановить данные позже:

class Person
  attr_reader :first_name, :last_name, :height, :awesomeness
  def initialize(first_name)
    @first_name = first_name
  end

  def update(info)
    info.each do |key, value|
      instance_variable_set("@#{key}", value) if respond_to?(key)
    end
  end

  def to_h
    { first_name: self.first_name, last_name: self.last_name, awesomeness: self.awesomeness, height: self.height }
  end
end

people = keys.each_with_object({}) do |k, person_map|
  person_map[k[:first_name]] = Person.new(k[:first_name])
end

data.each do |people_info|
  people_info.each do |first_name, info|
    if people[first_name]
      people[first_name].update(info)
    end
  end
end

p people.values.map{ |p| p.to_h }

#=> [{:first_name=>"blake", :last_name=>"johnson", :awesomeness=>10, :height=>"74"}, {:first_name=>"ashley", :last_name=>"dubs", :awesomeness=>9, :height=>60}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...