7

我有一个 powershell 脚本,我在其中执行以下操作

$somePSObjectHashtables = New-Object Hashtable[] $somePSObject.Length;
$somePSObjects = Import-CSV $csvPath
0..($somePSObject.Length - 1) | ForEach-Object {
    $i = $_;
    $somePSObjectHashtables[$i] = @{};
    $somePSObject[$_].PSObject.Properties | ForEach-Object {
        $somePSObjectHashtables[$i][$_.Name] = $_.Value;
    }
}

我需要这样做,因为我想在 CSV 中制作几个不同的数据副本以执行几个不同的操作。从某种意义上说,我正在对PSObject的结果数组执行“INNER JOIN” 。$somePSObjectHashtables我可以轻松地使用ForEach-Object迭代并在数组的每个成员上调用Hashtable.Clone() 。然后我可以New-Object PSObject -Property $someHashTable[$i]用来获取 PSObject 的深层副本。

我的问题是,是否有一些更简单的方法来制作深层副本,而无需中间哈希表?

4

3 回答 3

9

请注意,这是一个更短,也许更简洁的版本(我很喜欢):

$data = Import-Csv .\test.csv

$serialData = [System.Management.Automation.PSSerializer]::Serialize($data)

$data2 = [System.Management.Automation.PSSerializer]::Deserialize($serialData)

注意:然而,奇怪的是,它不保持有序哈希表的顺序。

$data = [ordered] @{
    1 = 1
    2 = 2
}

$serialData = [System.Management.Automation.PSSerializer]::Serialize($data)

$data2 = [System.Management.Automation.PSSerializer]::Deserialize($serialData)
$data2

将输出:

Name                           Value
----                           -----
2                              2
1                              1

而对于其他类型,它工作得很好:

$data = [PsCustomObject] @{
    1 = 1
    2 = 2
}

$data = @(1, 2, 3)
于 2019-06-28T07:36:54.357 回答
6

为了获得真正的深度副本,我们可以使用二进制序列化(假设所有数据都是可序列化的;对于来自 CSV 的数据肯定是这种情况):

# Get original data
$data = Import-Csv ...

# Serialize and Deserialize data using BinaryFormatter
$ms = New-Object System.IO.MemoryStream
$bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$bf.Serialize($ms, $data)
$ms.Position = 0
$data2 = $bf.Deserialize($ms)
$ms.Close()

# Use deep copied data
$data2
于 2012-02-09T07:27:34.410 回答
3

这是我用作函数的更短的一个:

using namespace System.Management.Automation
function Clone-Object ($InputObject) {
    <#
    .SYNOPSIS
    Use the serializer to create an independent copy of an object, useful when using an object as a template
    #>
    [psserializer]::Deserialize(
        [psserializer]::Serialize(
            $InputObject
        )
    )
}
于 2020-06-24T15:55:19.863 回答