добавить пару ключ-значение к ha sh в первом массиве в зависимости от подстроки из второго массива - PullRequest
1 голос
/ 25 марта 2020

У меня есть массив с хешами и другой массив со строками. Я хотел бы добавить пару ключ-значение к ha sh в первом массиве в зависимости от подстроки из второго массива:

учитывая:

export_configs = [
  {"foo"=>[{"state"=>"a"}, {"format"=>"aa"}, {"time"=>120}]}, 
  {"bar"=>[{"state"=>"b"}, {"format"=>"bb"}, {"time"=>30}]}, 
  {"baz"=>[{"state"=>"c"}, {"format"=>"cc"}, {"time"=>5}]}
]

topics = [
  "downloads/foo/7s699GToRzf9ViqGU5js/export", "downloads/bar/o679WbgrcNAJepprCWzR/export", "downloads/baz/_s5HQWr1xxq5yB7zPPhQ/export"
]

цель: добавить новый ключ "url" со значением из @topics в зависимости от подстроки ключа ha sh, например. "downloads / foo /" или "... / bar / ...", чтобы это выглядело так:

Результат:

export_configs = [
  {"foo"=>[{"state"=>"a"}, {"format"=>"aa"}, {"time"=>120}, {"url"=>"downloads/foo/7s699GToRzf9ViqGU5js/export"}]}, 
  {"bar"=>[{"state"=>"b"}, {"format"=>"bb"}, {"time"=>30}, {"url"=>"downloads/bar/o679WbgrcNAJepprCWzR/export"}]}, 
  {"baz"=>[{"state"=>"c"}, {"format"=>"cc"}, {"time"=>5}, {"url"=>"downloads/baz/_s5HQWr1xxq5yB7zPPhQ/export"}]}
]

моя попытка:

export_configs.map do |topic|
  topics.each do |t| 
    t.include? topic.first.keys[0]
    topic.merge("url" => t) 
  end
end

Но я получаю ошибку:

NoMethodError: undefined method `keys' for #<Array:0x0000000001cbe8b8>```

Ответы [ 3 ]

0 голосов
/ 25 марта 2020

Но я получаю ошибку

Это потому, что вы делаете topic.first.keys вместо topic.keys.first; разница в том, что topic.first ведет себя как topic.to_a.first, а Hash#to_a возвращает массив пар ключ / значение, например [[k1, v1], [k2, v2], ...].

Приведенное ниже решение работает наоборот; он перебирает export_configs, а затем пытается найти соответствующую топи c. В вашем примере каждый export_config га sh содержит одну пару ключ / значение, но я не вижу причины, по которой их не может быть больше, поэтому этот код выполняет еще один l oop внутри.

Он также использует Enumerable#find для извлечения объекта из массива, который соответствует определенному предикату; это особенно полезно для вашей проблемы, несмотря на то, что она не самая быстрая.

export_configs.map do |config|
  # defensive: there could be more keys in config
  config.map do |key, values|
    # this operation scans topics each time, not very fast
    topic = topics.find { |url| url.include? key }
    # make a copy here, so that original variable isn't modified
    values = values + [{ 'url' => topic }] if topic
    [key, values]
  end.to_h
end
0 голосов
/ 25 марта 2020

Вы получаете ошибку, потому что topic.first является массивом. Это потому, что вы звоните Enumerable # first Ha sh (который, как я вижу, возвращает массив, даже если он не задокументирован). проверить это:

export_configs.each do |topic|
  topics.each do |t|
    p topic 
    p topic.first
    p topic.keys.first # <-- this is the guy, see next
  end
end

Вы можете получить свой результат, передав его в массив, не сливаясь с ха sh (это изменит содержание export_configs:

export_configs.each do |topic|
  topics.each do |t|
    key = topic.keys.first
    if t.include? key
      topic[key] << {'url' => t}
    end
  end
end


Другой вариант

Я бы сопоставил URL-адреса с ха sh, просто чтобы быть уверенным, что в других местах нет "foo", "bar", "baz" url (изменяет содержимое export_configs):

topics_h = topics.map { |url| [url.split('/')[1], url] }.to_h
#=> {"foo"=>"downloads/foo/7s699GToRzf9ViqGU5js/export",
#=>  "bar"=>"downloads/bar/o679WbgrcNAJepprCWzR/export",
#=>  "baz"=>"downloads/baz/_s5HQWr1xxq5yB7zPPhQ/export"}

Затем l oop через новый га sh:

topics_h.each do |k, v|
  export_configs.each do |h|
    h[k] << {'url' => v} if h.key? k
  end
end

#=> [{"foo"=>[{"state"=>"a"}, {"format"=>"aa"}, {"time"=>120},{"url"=>"downloads/foo/7s699GToRzf9ViqGU5js/export"}]},
#=>  {"bar"=>[{"state"=>"b"}, {"format"=>"bb"}, {"time"=>30}, {"url"=>"downloads/bar/o679WbgrcNAJepprCWzR/export"}]},
#=>  {"baz"=>[{"state"=>"c"}, {"format"=>"cc"}, {"time"=>5},  {"url"=>"downloads/baz/_s5HQWr1xxq5yB7zPPhQ/export"}]}]
0 голосов
/ 25 марта 2020
export_configs.each do |topic|
  topics.each do |t|
    topic.merge!({'url' => t}) if t.include? topic.keys[0]
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...