【问题标题】:Split hastable at key/value pair在键/值对处拆分 hastable
【发布时间】:2017-08-02 20:11:17
【问题描述】:

如何从特定的键/值对开始拆分哈希表?

我有如下的哈希表,只是更长:

名称 值 ---- ----- 名称 Alpha 2 岁 定位技巧 开始日期 01-01-31 结束日期未知 名称 Corax 21 岁 位置潜行 收入 40'000 结束日期未知 名字荷鲁斯 22 岁 位置已死 为什么是异端 结束日期 03-30-30

我尝试了Group-Object,但失败了。

我特别想按姓名分开,除了姓名、年龄和职位之外的所有内容都不一致。

我的实际问题是,当 Why = Heresy 时,我想解析 NameAge 的哈希表>,不幸的是,数据的原始来源是一个字符串列表,这就是我将其转换为哈希表的原因。

【问题讨论】:

  • 我可能弄错了,但哈希表被有意设计为没有“位置”,这与数组不同。我认为您想专门删除名称、年龄等值。如果您的某些记录中有键名您不知道这些键是什么,那么您可以做相反的事情并只保留您想要的特定键吗? $hashtable | select Name, Age,Position 例如?
  • 我已经更新了我的原始帖子,但是是的......我有点需要在 WHYHeresy 时获取姓名和年龄......而且我可以弄清楚如何像这样解析我的数据,是从一个表变成多个对象或多个表
  • @A.Zia 你能扩展一下吗?当Why -eq 'Heresy' 时,你到底想用NameAge 做什么?
  • @A.Zia 在这种情况下,听起来您有一个 array 哈希表,而不是一个,并且您正在尝试过滤它们。请参阅我的编辑。如果您展示用于创建原始哈希表或哈希表数组的代码,也会有所帮助。
  • 根据您的示例输出,您的哈希表有多个具有相同名称的键。这是不可能的。哈希表最突出的特点是它们的键是唯一的。请说明您是如何创建哈希表的(更可能是哈希表列表),并说明您对 Group-Object 的尝试以及失败的原因。

标签: powershell hash split hashtable


【解决方案1】:

哈希表没有顺序,因此您不能依赖“之前”和“之后”的概念。如果您知道一组完整键的具体名称,那么您可以遍历哈希表并构建两个新的,因此如果您希望一个哈希表包含名称、年龄和位置,而另一个包含其他所有内容,你可以这样做:

$New1 = @{}
$New2 = @{}

$KeysGroup1 = @('Name','Age','Position') # This could just be one value

$MyHashTable.GetEnumerator().ForEach({
    if ($_.Key -in $KeysGroup1) {
        $New1[$_.Key] = $_.Value
    } else {
        $New2[$_.Key] = $_.Value
    }
})

如果顺序对您很重要,您可以使用有序字典。您可以使用快捷方式通过在文字哈希表前面加上 [ordered] 类型加速器来创建文字有序字典:

$myOrdered = [ordered]@{ a = 1; z = 5; g = 2 }

从那里您可以执行与上述类似的依赖顺序的方法。

创建不基于文字的有序字典:

$myOrdered = New-Object System.Collections.Specialized.OrderedDictionary

# or in PowerShell v5

$myOrdered = [System.Collections.Specialized.OrderedDictionary]::new()

$myOrdered.Add('key','value')

基于 cmets 编辑

这听起来更像是您拥有的 一个哈希表数组,而您现在想要过滤这些。

[hashtable] 可以(并且经常)用作一种原型对象,它对此非常有用,因为它通常支持相同的语法,并且具有内置的文字支持。

但是您开始遇到它们的限制,此时我认为您想要处理对象数组而不是哈希表数组。

幸运的是,有很多简单的方法可以直接从哈希表在 PowerShell 中创建对象:

$obj = New-Object -TypeName PSObject -Property $myHash
$obj = [PSCustomObject]$myHash

$objArray = $myHashArray.ForEach({[PSCustomObject]$myHash})

一旦你得到了你的对象数组,真正的乐趣就开始了:

$heretics = $objArray.Where({$_.Why -eq 'Heresy'})

您会注意到我什至没有费心过滤掉这里的其他属性。你不应该,除非你真的需要。然后您可以使用Select-Object 或仅访问您需要的属性。因此,出于显示目的,您可以这样做:

$heretics | Format-Table Name,Age

你可以用一个对象做更多你不能用哈希表做的事情,比如添加特殊类型的属性:

$objArray | Add-Member -MemberType ScriptProperty -Name IsHeretic -Value { $this.Why -eq 'Heresy' } -Force

$heretics = $objArray.Where({$_.IsHeretic})

【讨论】:

    【解决方案2】:

    所以,最后;我想通了,非常感谢@briantist 指导正确的方向。

    我的解决方案代码是:

    $startobj =  (0..($hastable.count -1)) | where {$hashtable[$_].keys -like "*Name*"}
    $endobj = (0..($hashtable.count -1)) | where {$hashtable[$_].keys -like "*End date*"}
    $objindex = (0..($hashtable.count -1))
    $numberofobjindex = 0..($hashtable.Where({$_.keys -like "*Name*"}).count - 1)
    
    
    $hashtableparsed = foreach ($numba in $numberofobjindex) {
      $Conv2data = $hashtable[($startobj[$numba]..$endobj[$numba])] 
        [PSCustomObject] @{
        Name = $Conv2data.Name
        Age = $Conv2data.Age
        Why = $Conv2data.Why
    
              }
       }  
    
    $hashtableparsed
    

    我意识到我看到的哈希表数据有一个重复的模式,每个循环开始时Name,结束时End date

    所以我基本上对哈希表进行了索引,并标记并索引了循环开始和结束的所有实例。

    然后我计算了周期数,FOR EACH 周期捕获了特别是该周期行中的哈希表数据的数据,并将其转换为PSCustomObject

    【讨论】:

      猜你喜欢
      • 2016-04-19
      • 2021-07-14
      • 1970-01-01
      • 2011-06-22
      • 2015-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多