PowerShell 数组元素比较

3

可能我错过了一些简单的东西,所以提前道歉。我也意识到可能有更好的方法,我也愿意尝试。

我正试图运行一个PowerShell脚本,它将查看一个值数组,比较它们以查看数组中两个元素之间的差异值。

以下是我正在使用的样本数据集,它从CSV导入到powershell中进行测试:

1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.7, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.7, 2.9, 3.0

我要做的是遍历这个列表,并将第二个条目与第一个比较,将第三个与第二个比较,将第四个与第三个比较,以此类推,仅当该元素的值至少比先前元素大0.2时,将该元素添加到$export中。

以下是我尝试过的内容:

$import = get-content C:/pathtoCSVfile
$count = $import.Length-1;
$current=0;

Do 
{    
    $current=$current+1;
    $previous=$current-1

    if (($import[$current]-$import[$previous]) -ge 0.2)
    {
        $export=$export+$import[$current]+"`r`n";
    }
} 
until ($current -eq $count)

现在我已经使用Trace进行了运行,并为$current和$previous分配了值,并按照每个循环中if条件中描述的方式运行了两者的减法,但仅对于值为2.7($import[14]-$import[13]),它才注册了if条件已经满足,因此只剩下一个值为2.7的$export变量。我原本期望其他值(1.7、1.9和2.9)也将被添加到$export变量中。

再次强调,这可能是我忽视了的一些愚蠢/显而易见的事情,但我似乎无法弄清楚。提前感谢您能提供的任何见解。


$export是标量值还是数组?如果它是一个数组,请定义$export = @() - lit
一个核心问题是$import是一个字符串而不是一个数组。 - lit
@lit: 除非 C:/pathtoCSVfile 只包含 1 行,否则 get-content C:/pathtoCSVfile 的输出是一个数组(由行组成)。按照现有的写法,$export 构建了一个单一的、多行的 [string] 实例。 - mklement0
1个回答

6
问题在于,十进制小数在隐式使用的[double]数据类型中没有精确表示,导致舍入误差引起您的-ge 0.2比较产生意外结果。

以下是一个简单的例子,使用带有小数点的数字文字时,PowerShell 隐式使用的就是[double]值:

PS> 2.7 - 2.5 -ge 0.2
True  # OK, but only accidentally so, due to the specific input numbers.

PS> 1.7 - 1.5 -ge 0.2
False  # !! Due to the inexact internally binary [double] representation.

如果你强制计算使用[decimal]类型,问题将会消失。
应用于上述示例(在PowerShell中将数字文本后缀添加d使其成为[decimal]):
PS> 1.7d - 1.5d -ge 0.2d
True # OK - Comparison is now exact, due to [decimal] values.

应用于更符合PowerShell惯用语言的重新构建代码的背景下:
# Sample input; note that floating-point number literals such as 1.0 default to [double]
# Similarly, performing arithmetic on *strings* that look like floating-point numbers
# defaults to [double], and Import-Csv always creates string properties.
$numbers = 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.7, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.7, 2.9, 3.0

# Collect those array elements that are >= 0.2 than their preceding element
# in output *array* $exports.
$exports = foreach ($ndx in 1..($numbers.Count - 1)) {
  if ([decimal] $numbers[$ndx] - [decimal] $numbers[$ndx-1] -ge 0.2d) {
    $numbers[$ndx] 
  }
}

# Output the result array.
# To create a multi-line string representation, use $exports -join "`r`n"
$exports

上面的代码产生以下结果:
1.7
1.9
2.7
2.9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接