Ruby, как развернуть хеш-таблицу и объединить ее значения - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть следующая таблица в формате yaml:

:first_directory:
 :component1:
  - component1.c
  - component1.h
 :component2:
  :component2_A:
   :src:
    - component2_A.c
   :inc:
    - component2_A.h

Когда я печатаю содержимое хэша, я получаю:

{:first_directory=>{:component1=>["component1.c", "component1.h"], :component2=>{:component2_A=>{:src=>["component2_A.c"], :inc=>["component2_A.h"]}}}}

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

first_directory/component1/component1.c
first_directory/component1/component1.h
first_directory/component2/component2_A/src/component2_A.c
first_directory/component2/component2_A/inc/component2_A.h

Каков самый чистый и лучший способ добиться этого?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Поскольку строка YAML использует отступ для обозначения структуры, вы можете получить желаемый результат, работая непосредственно со строкой, используя стек.

arr=<<_.lines
:first_directory:
 :component1:
  - component1.c
  - component1.h
 :component2:
  :component2_A:
   :src:
    - component2_A.c
   :inc:
    - component2_A.h
_
  #=> [":first_directory:\n",
  #    " :component1:\n",
  #    "  - component1.c\n",
  #    "  - component1.h\n",
  #    " :component2:\n",
  #    "  :component2_A:\n",
  #    "   :src:\n",
  #    "    - component2_A.c\n",
  #    "   :inc:\n",
  #    "    - component2_A.h\n"] 

def rollup(stack)
  stack.transpose.last.join('/')
end

stack = []

arr.each_with_object([]) do |line,arr|
  indent = line =~ /\S/
  line.gsub!(/[:\s-]/, '')
  if stack.any? && indent <= stack.last.first
    arr << rollup(stack)
    stack.select! { |ind,_| ind < indent }
  end
  stack << [indent, line]
end << rollup(stack)
  #=> ["first_directory/component1/component1.c", 
  #    "first_directory/component1/component1.h", 
  #    "first_directory/component2/component2_A/src/component2_A.c", 
  #    "first_directory/component2/component2_A/inc/component2_A.h"] 
0 голосов
/ 04 февраля 2019

Этот метод должен работать лучше всего:

def print_hash(hash_node, prev_string=nil)
  if hash_node.class == Array
    hash_node.each {|element| puts "#{prev_string}#{element}"}
  else # it is an inner hash
    hash_node.each do |key, value|
      print_hash(value, "#{prev_string}#{key}/")
    end
  end
end

print_hash(content_as_a_hash)

Тестовый прогон:

content_as_a_hash = {:first_directory=>{:component1=>["component1.c", "component1.h"], :component2=>{:component2_A=>{:src=>["component2_A.c"], :inc=>["component2_A.h"]}}}}

print_hash(content_as_a_hash)    

Результаты:

first_directory/component1/component1.c
first_directory/component1/component1.h
first_directory/component2/component2_A/src/component2_A.c
first_directory/component2/component2_A/inc/component2_A.h
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...