2017-02-20 55 views
0

Пусть говорят, у меня есть массив в следующем формате:Получить конкретную информацию из многомерного массива

arr = [{ 
     "id":"11", 
     "children":[ 
         { "id":"9"}, 
         { "id":"5", "children":[ {"id":"4"} ] } 
        ] 
     }, 
     { 
     "id":"10", 
     "children":[{ "id":"7"} ] 
     } 
     ] 

А теперь я хотел бы получить все идентификаторы, которые очевидны в этом массиве:

11,9,5,4,10,7 

для этого я хотел бы использовать рекурсивный код, подобный этому:

ids = [] 

def find_ids arr 
arr.each do |entry| 
    ids << entry["id"] if entry["id"] 
    find_ids(entry["children"]) if entry["children"] 
end 
end 

Что бы вы сделали, чтобы получить идентификаторы?

Возможно, вы знаете очень короткую версию?

Благодаря

+1

Джон, я доверяю редактировать я сделал все в порядке с вами. Я переформатировал входной массив, чтобы выявить его структуру, а также избежать необходимости прокрутки читателей по горизонтали, чтобы увидеть его. Я также привязал к нему переменную ('arr'), чтобы читатели могли ссылаться на переменную, не определяя ее. Было бы полезно (когда бы вы приводили пример) показать желаемый результат в качестве объекта Ruby. Здесь вы можете запросить '[11, 9, 5, 4, 10, 7]'. –

+0

Сделайте это '[" 11 "," 9 "," 5 "," 4 "," 10 "," 7 "]', если вы не хотите, чтобы строки были преобразованы в целые числа. –

+0

Я не читал ваш вопрос, прежде чем публиковать свой ответ, который почти совпадает с тем, что вы предлагаете, за исключением того, что я разрешал пары ключ-значение, где ключ не ': id', а значение не является массивом. Заметьте '{" id ": 1} # => {: id => 1}', то есть кавычки являются избыточными (и нужны только тогда, когда строка содержит пробел ('{" ab ": 1} # = > {: "ab" => 1} '). В результате' {"id": 1} ["id"] # => nil'. Вам нужно '{id: 1} [: id] # = > 1'. –

ответ

0

Или, если вы хотите использовать более короткую версию:

def get_ids(arr) 
    p =->(hsh) { Array === hsh["children"] ? ([hsh["id"]] + hsh["children"].map(&p)) : hsh["id"] } 

    arr.map(&p).flatten 
end 

get_ids(arr) 
# => ["11", "9", "5", "4", "10", "7"] 
1
def grab_ids(arr) 
    arr.each_with_object([]) do |h,a| 
    h.each do |k,v| 
     case v 
     when Array 
     a.concat(grab_ids(v)) 
     else 
     a << v if k == :id 
     end 
    end 
    end 
end 

grab_ids arr 
    #=> ["11", "9", "5", "4", "10", "7"] 
1

Другой способ заключается в использовании лямбда:

def get_ids(arr) 
    p = ->(a, exp) do 
    a.each do |hsh| 
     exp << hsh["id"] 
     p.(hsh["children"], exp) if Array === hsh["children"] 
    end 
    exp 
    end 
    p.(arr, []) 
end 

get_ids(arr) 
# => ["11", "9", "5", "4", "10", "7"]