递归搜索/比较嵌套的Hashtables?

时间:2018-02-08 16:31:27

标签: powershell recursion hashtable

首先,我要道歉,下面的数据结构可能写得不正确。我动态地在代码中创建了哈希,并且我不太擅长尝试表示创建的内容。

$Sailings= @{
    'Arrivals' = @{
        $DynamicKey_booking_Ref = @{
            'GoingTo' = 'Port1';
            'Scheduled' = '09:05';
            'Expected' = '10:09';
            'Status' = 'Delayed'
        }; 
    'Departures' = @{
        $DynamicKey_booking_Ref = @{
            'ArrivingFrom' = 'Port1';
            'Scheduled' = '09:05';
            'Expected' = '09:05';
            'Status' = 'OnTime'
        }; 
    }
}

我通常会像这样访问数据。 (希望确认我正在使用的结构):

$Sailings.Arrivals.PDH083.GoingTo which returns "Port1"
$Sailings.Arrivals.PDH083.Scheduled which returns "09:05"

此示例中的PDH083是基于预订参考的动态创建的密钥。

我想要做的是将此结构与另一个相同的结构进行比较,但可能具有不同的值。例如。这两个元素是一样的吗?

$Sailings.Arrivals.PDH083.GoingTo =  "Port1"
$Output.Arrivals.PDH083.GoingTo  = "Port5555"

如果它们不相同则捕获差异和不同的路径/密钥。然后在最后报告它们。

我正在努力编写的是一个递归循环,它可以向下走到最后一个元素,然后将它与$output进行比较。虽然我的哈希值现已修复,但我想允许更多嵌套哈希值可能会在以后添加更低的值。这是否可以轻松完成?

我用过

($Sailings.Arrivals.keys | ? {$Output.Arrivals.keys -notcontains $_})

显示丢失的键,但我无法理解为这些值执行此操作的类似/有效方法。我再次看到我可以使用.values,但它一次只是元素。

1 个答案:

答案 0 :(得分:1)

这是一个半递归示例,它返回树中所有叶子的路径的字符串表示。希望它能给你一些想法:

$Sailings = @{
   'Arrivals' = @{
        'PDH083' = @{
                        'GoingTo' = 'Port1'
                        'Scheduled' = '09:05'
                        'Expected' = '10:09'
                        'Status' = 'Delayed'
        }
    }
    'Departures' = @{
        'PDH083' = @{
                        'ArrivingFrom' = 'Port1'
                        'Scheduled' = '09:05'
                        'Expected' = '09:05'
                        'Status' = 'OnTime'
        }
    }
}

function Roam($arg, $result="") {
    if(!($arg -is [Hashtable])) {
        return "$result/$arg"
    }

    foreach($pair in $arg.GetEnumerator()) {
        Roam $pair.value "$result/$($pair.key)"
    }
}
Roam $Sailings

if停止条件,在设计递归操作时应该首先询问:当我有结果时

假设你站在一棵巨大的树的根部,并且你被赋予了一个任务,即将路线映射到该树的每一个假期,每一个转弯都在从树干到休假的树枝上向左或向右转。压倒性的,是吗?但是想想找到一条通往单一假期的路线,无论哪一条来自无数。

你开始爬山,到达第一个分支。你会转向左边还是右边?无所谓。你决定采取左分支,并在纸上写下 left 。你到达下一个分支,为了有趣的事情向右转,写下正确的。在几个分支之后,你带着像左,右,右,左,右等的笔记,直到(因为树通常不会产生循环)最终没有更多的攀登,但只有一个假用你的字体。

你做到了!您将整个(并且只有一个)路径映射到此单个假,现在可以跳下(希望树不会太高)并表示包含您的崇拜朋友路线的纸张。到达休假是停止条件。

但其他叶子怎么样?想象一下,你有一个奇怪的超级大国克隆自己。当你到达一个分支时,你克隆自己和你正在携带的纸张。如果向右转,则向右添加注释,但克隆向左移动,然后向下写 left 。在下一个分支上,你再次克隆自己和纸张,并记下你选择的方向,克隆的方向也是如此。你不必担心克隆,(也许你自己就是克隆人!)只要重复一遍,直到你完成一次离开并且可以跳出来。

$result论证是那张纸,原来它不是来自任何地方,它是空的。

因为数据结构中的所有叶子都是字符串,所以您也可以编写if语句,如:

if($arg -is [String])

GetEnumerator怎么样? Hashtables通常不在PowerShell中订购。我们不能选择第一对,第二对或第六对。但是您的数据结构分支到比左右更多的方向,因此Hashtable必须作为一群人排序到Array到队列,因此我们可以使用foreach循环将我们的克隆发送到他们的路径。 (我们可以用递归代替那个循环,但是让它成为)

因此在函数调用Roam $pair.value "$result/$arg"中,第一个参数是前面的分支,第二个参数是我们刚刚添加当前方向的那张纸。

推荐:你不需要争分夺秒,即使前几章也很有启发性。 计算机程序的结构和解释 https://mitpress.mit.edu/sicp/full-text/book/book.html