Строка, по-видимому, описывает целевое дерево, за исключением менеджеров по учету, у
'12,Accounting managers,000.000.114.000'
, похоже, нет начальника.Поэтому я добавил
'14,Accounting big cheese,000.000.114'
Вот данные.
data =<<-_
ID, NAME, PATH
---------
1,Valve,000
2,Steam,000.000
3,Sales,000.000.000
4,Developers,000.000.112
7,Designers,000.000.112.000
8,Game Designers,000.000.112.000.000
9,UI Designers,000.000.112.000.002
10,Web Designers,000.000.112.000.001
11,3D Designers,000.000.112.000.003
14,Accounting big cheese,000.000.114
12,Accounting managers,000.000.114.000
13,Accounting topmanagers,000.000.114.000.000
_
Мы можем использовать split("\n")
, чтобы преобразовать эту строку в массив строк, а затем определить происхождение каждогоузел следующим образом.
r1, r2, *rest = data.split("\n")
str = [
r1,
r2,
rest.map do |s|
parent_match = s[/(?:\d{3}\.)*\d{3}(?=\.\d{3})/]
parent = arr.find { |ss| parent_match == ss[/(?:\d{3}\.)*\d{3}/] }
parent.nil? ? "#{s}, nil" : "#{s}, #{ parent[/\d+/] }"
end
].join("\n")
puts str
ID, NAME, PATH
---------
1,Valve,000, nil
2,Steam,000.000, 1
3,Sales,000.000.000, 2
4,Developers,000.000.112, 2
7,Designers,000.000.112.000, 4
8,Game Designers,000.000.112.000.000, 7
9,UI Designers,000.000.112.000.002, 7
10,Web Designers,000.000.112.000.001, 7
11,3D Designers,000.000.112.000.003, 7
14,Accounting big cheese,000.000.114, 2
12,Accounting managers,000.000.114.000, 14
13,Accounting topmanagers,000.000.114.000.000, 12
В блоке map
предположим, что
s = '8,Game Designers,000.000.112.000.000'
затем
parent_match = s[/(?:\d{3}\.)*\d{3}(?=\.\d{3})/]
#=> "000.000.112.000"
parent_match
- это строка всех тройок цифр, разделенных точками в s
, за исключением последнего периода, за которым следует последняя тройка цифр.Регулярное выражение гласит: «соответствует нулю или нескольким группам из 3 цифр, за которыми следует точка, за которой следуют 3 цифры, при условии, что за этим совпадением сразу следует точка и 3 цифры ((?=\.\d{3})
) являются положительным прогнозом * 1030».*).
Затем мы перебираем rest
в поисках элемента, который заканчивается на parent_match
:
parent = rest.find { |ss| parent_match == ss[/(?:\d{3}\.)*\d{3}/] }
#=> "7,Designers,000.000.112.000"
Регулярное выражение /(?:\d{3}\.)*\d{3}/
читает "соответствует нулю или более группам3 цифры, после которых следует точка, а затем 3 цифры ".
В следующей строке:
parent.nil?
#=> false
, поэтому блок возвращает
"#{s}, #{ parent[/\d+/] }"
#=> "8,Game Designers,000.000.112.000.000, 7"
parent[/\d+/]
простоизвлекает символ (ы) в начале parent
.
Если бы я не добавил строку
14,Accounting big cheese,000.000.114
, следующая строка ('12,Accounting ...'
) закончилась бы, ', nil'
.