避免不可知论铁血阵列在PowerShell中压扁 [英] Avoiding Agnostic Jagged Array Flattening in Powershell

查看:132
本文介绍了避免不可知论铁血阵列在PowerShell中压扁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行到PowerShell中一个有趣的问题,一直没能找到一个解决的办法。当我谷歌(和找东西像<一个href=\"http://stackoverflow.com/questions/1390782/jagged-powershell-array-is-losing-a-dimension-when-only-one-element-exists\">this帖子),什么能所涉及的什么,我试图做的来了,所以我想我会在这里发表的问题。

I'm running into an interesting problem in Powershell, and haven't been able to find a solution to it. When I google (and find things like this post), nothing quite as involved as what I'm trying to do comes up, so I thought I'd post the question here.

问题具有与一个的外数组长度多维数组做。看来PowerShell是关于扁平状阵列@(@('A'))变成 @('A')。这是第一个片段(提示是>,顺便说一句):

The problem has to do with multidimensional arrays with an outer array length of one. It appears Powershell is very adamant about flattening arrays like @( @('A') ) becomes @( 'A' ). Here is the first snippet (prompt is >, btw):

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

所以,我想有 $ a [0] .gettype()。IsArray的是真实的,这样我可以索引值 $ A [0] [0] (现实世界中的场景正在处理动态数组一个循环里面,我想获得的值 $ A [ $ i] [$ J] ,但如果<内物品不被识别为一个数组,但作为一个字符串(在我的情况),你开始索引到字符串中的字符,如code> $ a [0] [0] -eq'T')。

So, I'd like to have $a[0].gettype().isarray be true, so that I can index the value as $a[0][0] (the real world scenario is processing dynamic arrays inside of a loop, and I'd like to get the values as $a[$i][$j], but if the inner item is not recognized as an array but as a string (in my case), you start indexing into the characters of the string, as in $a[0][0] -eq 'T').

我有一对夫妇的长code的例子,所以我已经发布他们在最后。而且,以供参考,这是Windows 7旗舰版安装PSV2和PSCX。

I have a couple of long code examples, so I have posted them at the end. And, for reference, this is on Windows 7 Ultimate with PSv2 and PSCX installed.

考虑的 code例如1 :我建立一个简单的数组使用手动+ =操作符。中间阵列 $ W 变平,因此不会被添加到最终的阵列正常。我已经找到解决方案,在线为类似的问题,这主要涉及将一个逗号内阵列之前,迫使外阵列不是扁平化,这不工作,但同样,我在寻找能够建立一个循环内阵列的解决方案(阵列的交错数组,处理CSS文件),所以如果我添加的主要逗号单一元素的数组(作为中间阵列实施 $ Y ),我想做同样为其他阵列(如 $ Z而言),但不利影响如何 $ Z而言添加到最后一个数组。

Consider code example 1: I build a simple array manually using the += operator. Intermediate array $w is flattened, and consequently is not added to the final array correctly. I have found solutions online for similar problems, which basically involve putting a comma before the inner array to force the outer array to not flatten, which does work, but again, I'm looking for a solution that can build arrays inside a loop (a jagged array of arrays, processing a CSS file), so if I add the leading comma to the single element array (implemented as intermediate array $y), I'd like to do the same for other arrays (like $z), but that adversely affects how $z is added to the final array.

现在考虑的 code例如2 :这是更接近我有实际的问题。当一个元素的多维数组是由函数返回的,它被夷为平地。这是正确的离开函数之前。再次,这些都是例子,我真的想处理一个文件,而无需知道函数是否会回来与 @(@('色','黑')) @(@('色','黑'),@('背景色','白'))

Now consider code example 2: This is closer to the actual problem I am having. When a multidimensional array with one element is returned from a function, it is flattened. It is correct before it leaves the function. And again, these are examples, I'm really trying to process a file without having to know if the function is going to come back with @( @( 'color', 'black') ) or with @( @( 'color', 'black'), @( 'background-color', 'white') )

有没有人遇到过这一点,已经有人解决了这个?我知道我可以实例化框架对象,我假设一切都会好起来,如果我创建了一个对象[],或列表&LT;>,还是别的什么类似的,但我一直在处理这个一点点东西确保好像必须有做到这一点(而无需真正的实例化框架对象)一个正确的方式。

Has anybody encountered this, and has anybody resolved this? I know I can instantiate framework objects, and I'm assuming everything will be fine if I create an object[], or a list<>, or something else similar, but I've been dealing with this for a little bit and something sure seems like there has to be a right way to do this (without having to instantiate true framework objects).

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'

code例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'

谢谢,马特

推荐答案

有是同样的问题开始了另一个问题:<一href=\"http://stackoverflow.com/questions/803521/powershell-pitfalls\">http://stackoverflow.com/questions/803521/powershell-pitfalls 。它看起来像这是由设计完成的。

There is another question that starts with the same problem: http://stackoverflow.com/questions/803521/powershell-pitfalls . It looks like this is done by design.

我想如果返回,$沤而不是 $ RET ,它应该工作。

I think if you return ,$ret instead of $ret, it should work.

另外两个注意事项:


  • 您可以测试,如果该项目是由数组 $项目-is [阵列] (只是因为它看起来更像是PowerShell的;)

  • @()只对不属于数组项目的效果。如果您将 @(@(@(1))),你会得到一个INT项(数组@(@(@(1 )))[0] .gettype()返回的Int32)。
    因此, @(@('R','S'))相同,@('R','S')

  • you can test, if the item is array by $item -is [array] (just because it looks more like PowerShell ;)
  • @() has effect only on items that are not arrays. If you chain @(@(@(1))), you will get an array with one int item (@(@(@(1)))[0].gettype() returns Int32).
    So, @( ,@('r', 's') ) is the same as ,@('r', 's').

这篇关于避免不可知论铁血阵列在PowerShell中压扁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆