Вопрос

Я сталкиваюсь с интересной проблемой в PowerShell, и я не смог найти решение. Когда я Google (и нахожу что -то вроде эта почта), ничего не так вовлечено, как то, что я пытаюсь сделать, не возникает, поэтому я подумал, что опубликую здесь вопрос.

Проблема связана с многомерными массивами с длиной внешней массивы одной. Похоже, PowerShell очень непреклонен в отношении сглаживания массивов, таких как @( @('A') ) становится @( 'A' ). Анкет Вот первый фрагмент (подсказка>, кстати):

> $a =  @( @( 'Test' ) )
> $a.gettype().isarray
True
> $a[0].gettype().isarray
False

Итак, я хотел бы иметь $a[0].gettype().isarray быть правдой, чтобы я мог указать значение как $a[0][0] (Сценарий реального мира обрабатывает динамические массивы внутри цикла, и я хотел бы получить значения как $a[$i][$j], но если внутренний элемент не распознается как массив, а как строка (в моем случае), вы начинаете индексировать символы строки, как в $a[0][0] -eq 'T').

У меня есть пара длинных примеров кода, поэтому я опубликовал их в конце. И, для справки, это на Windows 7 Ultimate с установленными PSV2 и PSCX.

Рассмотреть возможность Пример кода 1: Я строю простой массив вручную, используя оператор +=. Промежуточный массив $w сглажен и, следовательно, не добавляется к окончательному массиву правильно. Я нашел решения в Интернете для аналогичных проблем, которые в основном включают в себя запятую перед внутренним массивом, чтобы заставить внешний массив не сгладить, что работает, но опять же, я ищу решение, которое может строить массивы в цикле ( зазубренный массив массивов, обработка файла CSS), поэтому, если я добавлю ведущую запятую в массив единых элементов (реализовано как промежуточный массив $y), Я хотел бы сделать то же самое для других массивов (например $z), но это отрицательно влияет на то, как $z добавляется в окончательный массив.

Теперь рассмотрим Пример кода 2: Это ближе к фактической проблеме, которая у меня есть. Когда многомерный массив с одним элементом возвращается из функции, он сплющивается. Это правильно, прежде чем оставить функцию. И опять же, это примеры, я действительно пытаюсь обработать файл, не зная, вернется ли функция с @( @( 'color', 'black') ) или с @( @( 'color', 'black'), @( 'background-color', 'white') )

Кто -нибудь столкнулся с этим, и кто -нибудь решил это? Я знаю, что могу создать создание фреймворвочных объектов, и я предполагаю, что все будет хорошо, если я создам объект [] или список <> или что -то еще подобное, но я имел дело с этим немного и чем -то Конечно, кажется, что должен быть правильный способ сделать это (без необходимости создавать экземпляры истинных структурных объектов).

Пример кода 1

function Display($x, [int]$indent, [string]$title)
{
  if($title -ne '') { write-host "$title`: " -foregroundcolor cyan -nonewline }
  if(!$x.GetType().IsArray)
  { write-host "'$x'" -foregroundcolor cyan }
  else
  {
    write-host ''
    $s = new-object string(' ', $indent)
    for($i = 0; $i -lt $x.length; $i++)
    {
      write-host "$s[$i]: " -nonewline -foregroundcolor cyan
      Display $x[$i] $($indent+1)
    }
  }
  if($title -ne '') { write-host '' }
}


### Start Program
$final = @( @( 'a', 'b' ), @('c'))
Display $final 0 'Initial Value'

### How do we do this part ??? ###########
                                        ##
$w = @( @('d', 'e') )                   ##
$x = @( @('f', 'g'), @('h') )           ##
# But now $w is flat, $w.length = 2     ##
                                        ##
                                        ##
# Even if we put a leading comma (,)    ##
# in front of the array, $y will work   ##
# but $w will not. This can be a        ##
# problem inside a loop where you don't ##
# know the length of the array, and you ##
# need to put a comma in front of       ##
# single- and multidimensional arrays.  ##
$y = @( ,@('D', 'E') )                  ##
$z = @( ,@('F', 'G'), @('H') )          ##
                                        ##
                                        ##
##########################################

$final += $w
$final += $x
$final += $y
$final += $z
Display $final 0 'Final Value'


### Desired final value: @( @('a', 'b'), @('c'), @('d', 'e'), @('f', 'g'), @('h'), @('D', 'E'), @('F', 'G'), @('H') )
### As in the below:
# 
# Initial Value:
# [0]:
#  [0]: 'a'
#  [1]: 'b'
# [1]:
#  [0]: 'c'
# 
# Final Value:
# [0]:
#  [0]: 'a'
#  [1]: 'b'
# [1]:
#  [0]: 'c'
# [2]:
#  [0]: 'd'
#  [1]: 'e'
# [3]:
#  [0]: 'f'
#  [1]: 'g'
# [4]:
#  [0]: 'h'
# [5]:
#  [0]: 'D'
#  [1]: 'E'
# [6]:
#  [0]: 'F'
#  [1]: 'G'
# [7]:
#  [0]: 'H'

Пример кода 2

function Display($x, [int]$indent, [string]$title)
{
  if($title -ne '') { write-host "$title`: " -foregroundcolor cyan -nonewline }
  if(!$x.GetType().IsArray)
  { write-host "'$x'" -foregroundcolor cyan }
  else
  {
    write-host ''
    $s = new-object string(' ', $indent)
    for($i = 0; $i -lt $x.length; $i++)
    {
      write-host "$s[$i]: " -nonewline -foregroundcolor cyan
      Display $x[$i] $($indent+1)
    }
  }
  if($title -ne '') { write-host '' }
}



function funA()
{
  $ret = @()
  $temp = @(0)
  $temp[0] = @('p', 'q')
  $ret += $temp
  Display $ret 0 'Inside Function A'
  return $ret # What about return ,$ret ? What about if $ret = @( @('p', 'q'), @('r', 's') ) -- would return ,$ret still work?
}

function funB()
{
  $ret = @( ,@('r', 's') )
  Display $ret 0 'Inside Function B'
  return $ret
}


### Start Program

$z = funA
Display $z 0 'Return from Function A'
$z = funB
Display $z 0 'Return from Function B'


### Desired final value: @( @('p', 'q') )  and same for r,s
### As in the below:
# 
# Inside Function A:
# [0]:
#  [0]: 'p'
#  [1]: 'q'
# 
# Return from Function A:
# [0]:
#  [0]: 'p'
#  [1]: 'q'

Спасибо, Мэтт

Это было полезно?

Решение

Есть еще один вопрос, который начинается с той же проблемы: PowerShell ловушки Анкет Похоже, это делается по дизайну.

Я думаю, если ты вернешься ,$ret вместо $ret, он должен работать.

Еще две заметки:

  • Вы можете проверить, если элемент массив $item -is [array] (Просто потому, что это больше похоже на PowerShell;)
  • @() влияет только на предметы, которые не являются массивами. Если вы цепь @(@(@(1))), вы получите массив с одним предметом (@(@(@(1)))[0].gettype() Возвращает Int32).
    Так, @( ,@('r', 's') ) такой же как ,@('r', 's').

Другие советы

Я попробовал то, что сказал Стю, и это сработало, используя этот пример:

function funC([int]$numOfPairs)
{
  $ret = @()
  if($numOfPairs -eq 1)
  { $ret = ,@('r','s') }
  elseif($numOfPairs -eq 2)
  { $ret = @('r','s'),@('t','u') }
  else
  { $ret = @('r','s'),@('t','u'),@('v','w') }

  Display $ret 0 "Inside Function C ($numOfPairs)"
  return ,$ret
}


### Start Program

$z = funC 1
Display $z 0 'Return from Function C(1)'
$z = funC 2
Display $z 0 'Return from Function C(2)'
$z = funC 3
Display $z 0 'Return from Function C(3)'
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top