#powershell
Вопрос:
У меня есть несколько списков, состоящих из таких строк (представьте их в виде дерева сортировки).:
$список 1:
data-pool data-pool.house 1 data-pool.house 1.door2 data-pool.house 1.door3 data-pool.house2 data-pool.house2.door 1
Чтобы упростить их анализ в виде дерева, как можно сделать отступ в зависимости от того, сколько .
символов встречается при удалении повторяющегося текста в начале строки? Например:
data-pool house 1 door2 door3 house2 door 1
То, как я подошел к этому, подсчитывая вхождения .
s, .split('.').Length-1
чтобы определить количество необходимых отступов, а затем добавляя пробелы, используя .IndexOf('.')
и .Substring(0, lt;positiongt;)
чувствует себя слишком сложным — или тогда я просто не могу понять, как это сделать менее сложным способом.
Комментарии:
1. Ваше решение кажется мне прекрасным?
2. Всегда ли число дочерних узлов находится в диапазоне от 1 до 2?
3. @ITM: Это может быть, но прохождение сотен — тысяч строк кажется тяжелым.
4. @SantiagoSquarzon: Нет, текст может сильно отличаться и быть практически любым.
5. Что я имел в виду в своем предыдущем комментарии, так это то, возможно ли иметь что-то подобное:
data-pool.house 1.door1.something.something.something.
? Или всегда будет 1 дверь и 1 дом?
Ответ №1:
Я думаю, что это должно работать до тех пор, пока количество узлов от строки к строке упорядочено, я имею в виду, что это не будет выглядеть «красиво», если, например, текущий узел содержит n
элементы, а следующий узел имеет n 2
или больше.
Чтобы представить это в перспективе, используйте этот список в качестве примера:
$list = @' data-pool data-pool.house 1 data-pool.house 1.door2 data-pool.house 1.door3 data-pool.house 1.door4.something1 data-pool.house2 data-pool.house2.door 1 data-pool.house2.door 2.something1 data-pool.house2.door 3.something1.something2 data-pool.house3 data-pool.house3.door 1 data-pool.house3.door 2 '@ -split 'r?n'
Функция indent
будет принимать каждую строку свой список и разбить его, используя .
в качестве разделителя, если количество элементов после разделения меньше или равно 1
он не будет выполнять какие-либо изменения и отображения этой строки как есть, иначе, он будет размножаться $IndentType
, содержащий 2 белых пространств по количеству элементов раскола массива минус 1 , и соединить его с последним элементом раскола массива.
function indent { param( [string]$Value, [string]$IndentType = ' ' ) $out = $Value -split '.' $level = $out.Count - 1 '{0}{1}' -f ($null,($IndentType*$level))[[int]($out.Count -gt 1)], $out[-1] } $list.ForEach({ indent $_ })
Образец:
data-pool house 1 door2 door3 something1 house2 door 1 something1 something2 house3 door 1 door 2
Комментарии:
1. Это работает, как и ожидалось, спасибо! Строки сортируются и упорядочиваются до выполнения этой функции, чтобы узлы и элементы должным образом сохранялись на своих местах.
2. @lapingultah это приятно знать и рад помочь.
3. @lapingultah не уверен, что я понимаю, не могли бы вы задать новый вопрос, подробно объясняющий это новое требование ?
Ответ №2:
подход к получению последнего элемента строки приведен ниже
## String $string = "data-pool.house 1" ## split the string into an array every "." $split = $string.split(".") ## return the last element of the array write-host $split[-1] -ForegroundColor Green
Затем протестировать каждую строку
$myArray = ("data-pool", "data-pool.house 1", "data-pool.house 1.door2", "data-pool.house 1.door3", "data-pool.house2", "data-pool.house2.door 1") ForEach($Name in $myArray) { ## String $Name = $Name.ToString() $string = $Name $split = $string.split(".") ## return the last element of the array write-host $split[-1] -ForegroundColor Green }
Комментарии:
1. Я не понимаю логики в этом.
$myArray
здесь уже приведено как строка, поэтому.ToString()
оно не требуется и$string = $Name
может быть опущено, используя только$split = $Name.split(".")
вместо этого. Также это не учитывает необходимые отступы.2. Так как у меня нет exchange для построения массива. Я использовал то, что вы предоставили, чтобы продемонстрировать, что вам нужно сделать.