【问题标题】:How to do ForEach only on objects in hashtable that match object in array如何仅对哈希表中与数组中的对象匹配的对象执行 ForEach
【发布时间】:2022-11-17 12:37:12
【问题描述】:

我有一个作业中使用的哈希表,每个 hash.key 都是一个作业名称:

$myhashtable = @{ 
    'somelocation'    = 'somevalue'
    'otherlocation'   = 'othervalue'
}

我针对一个函数运行哈希表,该函数是为哈希表中的每个对象运行的 Start-Job

foreach ( $location in $myhashtable.GetEnumerator() )
{
    SomeFunction
}

然后我得到停止工作的名称:

$joblist = Get-Job | Where-Object { $_.State -eq "Stopped" }
$joblist = $joblist.name

尝试对函数执行与上述相同的操作,但仅针对已停止的作业:

foreach( $location in $myhashtable.GetEnumerator() )
{
    if $location.key matches an object in $joblist}( 
    do SomeFunction for those $location.keys)
}

我尝试了各种foreachifwhere但无法命中。

谢谢!

【问题讨论】:

  • 那么你想匹配$Array,键还是值呢? IE。作业名称是数组键还是数组值? (挑剔:它实际上不是一个数组,而是一个Hashtable
  • “我已经尝试过各种 foreach if 和 where”,但您没有显示任何这些尝试。
  • 就目前而言,您的问题尚不清楚。如果要获取从作业创建的数组,则需要先使用receive-job。如果你想比较数组和/或对象,你可以使用Compare-Object
  • 另外请注意,哈希文字中不允许重复键,即您的$Array
  • @zett42 对我的术语混淆表示歉意,感谢您更正。我更新了帖子,以便更清楚地了解预期目标。

标签: arrays powershell foreach hashtable start-job


【解决方案1】:

正如@zett42 指出的那样,您的问题使用您命名为$Array。在我的回复中重命名它以避免混淆,但我认为下面的代码将完成您正在尝试做的事情。

PS> $myHashtable = @{
>> 'key1'   = 'value1'
>> 'key2'   = 'value2'
>> 'key3'   = 'value3'
>> }
PS> $joblist= 'key1', 'key2'
PS> $myHashtable.keys | ForEach-Object { if( $_ -in $joblist ){ $myHashtable[$_] } }
value1
value3

【讨论】:

  • 如果您有兴趣稍微调高一下,可以改用 .Where({}) 运算符:$myHashtable.GetEnumerator().Where{$_.key -in $joblist}.Value.Key 作为键名。
  • @Ben 这比我得到的更接近,但还不完全是。我希望在末尾获取键而不是值,而不是在函数中使用它们。目前我正在做foreach($hash in $hashtable.GetEnumerator()) { SomeFunction}而不是我的$joblist。之后,我尝试对 if foreach($hash in $hashtable.GetEnumerator()) { SomeFunction (if($_ -in $joblist){$myHashtable[$_])} 做同样的事情,但键不是值。
  • @Retrotube 我在解析您正在寻找的输出时遇到了一些麻烦。您能否更新您的问题以包括预期输出的内容?
  • @Ben 原始帖子已更新,希望它更清楚。为我的术语混淆道歉。
  • @ben 我建议你在最后的If 块中添加一个伪函数调用。阅读这个问题我认为这可能是最后一篇。
【解决方案2】:

这是一个可能的解决方案:

$myhashtable = @{ 
'somelocation'    = 'somevalue'
'otherlocation'   = 'othervalue'
}

# For each job that has stopped and whose name matches a key in $myhashtable
Get-Job | Where-Object { $_.State -eq Stopped -and $myhashtable.Contains( $_.Name ) } | 
    ForEach-Object {
        SomeFunction 
    }

当你有一个 hashtable 时,你通常不应该遍历它来在其他地方搜索密钥,这非常效率低下.而是反过来做,遍历要匹配的对象数组并在 hashtable 中进行查找,例如通过调用 .Contains 方法或使用索引运算符 []。如果给定的参数与 hashtable 的键之一匹配,则 .Contains 方法返回 $true。这是一个非常有效的操作,因为 hashtable针对快速查找键进行了优化.

【讨论】:

  • 事实证明这不是我想要的。它很接近,让我找到了我正在寻找的东西。我认为这种比较列表的方式与我需要的相反。将添加工作代码作为答案。
【解决方案3】:

这是执行我正在寻找的解决方案:

$JobList = Get-Job | Where-Object { 
    $_.State -eq "Stopped" -or $_.State -eq "Completed" -and $HashTable.Contains( $_.Name ) 
    }
Remove-Job $JobList.ID 
$JobList = @($JobList.name | ForEach-Object {[regex]::Escape($_)}) -join '|'
foreach($Hash in $HashTable.GetEnumerator()) {
    if( $Hash.key -match $JobList) {
        SomeFunction
        }
    }

我有一个基于此处帖子的先前解决方案,该解决方案仅适用于一次迭代或适用于所有迭代。这篇文章帮助我让它完全正常工作contains-or-match-several-values

为此想出了一个更好的方法:

$HashTable.GetEnumerator().ForEach({if($JobList.name.Contains($_.key)){Start-Function $($_.key)}})

这种方式不需要这一行:

$JobList = @($JobList.name | ForEach-Object {[regex]::Escape($_)}) -join '|'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2015-06-16
    • 1970-01-01
    • 2019-04-08
    相关资源
    最近更新 更多