【问题标题】:Comparing two arrays of similar objects, with a list of the unique properties as well比较两个相似对象的数组,以及唯一属性的列表
【发布时间】:2019-04-06 23:13:32
【问题描述】:

我有两个自定义对象数组 - $deploy 和 $directory。它们有 4 个共同的属性和 1 个独特的属性。我需要找到两个数组中 4 个公共属性相同的成员,但我还需要跟踪匹配项的 2 个唯一属性。

在具有定义相同属性的两个数组上使用 compare-object,-passthru 和 -includeequal 几乎是这样,但只给了我第一个(引用)对象及其唯一属性,而不是差异对象上的唯一属性。

所以我不能简单地比较两个数组并得到我需要的东西。我要么需要做一个嵌套循环,要么破解/找到某种“设置交集”功能。我只会处理每个数组的几十个成员,所以我不太关心性能。

你会采取什么方法?对于下面的简单示例,我希望跟踪所有匹配项的环境名称和部署目录。

$deploy
GameBuildVersion    : 68858.zip
OnlineVersion       : 70793.zip
ContentVersion      : 68858.69165-1.zip
ContentBuildVersion : 69165-1.zip
environmentname     : Staging35

$directory
GameBuildVersion    : 68858.zip
OnlineVersion       : 70793.zip
ContentVersion      : 68858.69165-1.zip
ContentBuildVersion : 69165-1.zip
deploymentDirectory : C:\deployer\script\deploy-AB

【问题讨论】:

  • 看看这个的full join部分...在PowerShell中合并数据——漫无目的的饼干怪物——ramblingcookiemonster.github.io/Join-Object
  • 试试Join-Object$deploy | FullJoin $directory GameBuildVersion, OnlineVersion, ContentVersion, ContentBuildVersion
  • @Lee_Dailey - 该函数仅适用于每个对象的单个属性,不幸的是,我需要对 *version 属性进行全 4 匹配。
  • @mfinni - 啊!我把full join 部分按要求做了。重读显然是不正确的。感谢您指出这一点! [咧嘴]

标签: arrays powershell compare set-intersection


【解决方案1】:

这可能不是最快的方法,但这是我想出的:

# create a string array storing the combined properties of the 4 common $deploy objects.
# convert these strings to lowercase, because later on we use IndexOf and that is case sensitive.
$commons = @()
$deploy | ForEach-Object {
    $commons += $("{0},{1},{2},{3}" -f $_.GameBuildVersion, $_.OnlineVersion, $_.ContentVersion, $_.ContentBuildVersion).ToLower()
}

# create an array to store the objects both arrays have in common, combined with their unique properties
$result = @()
$directory | ForEach-Object {
    $props = $("{0},{1},{2},{3}" -f $_.GameBuildVersion, $_.OnlineVersion, $_.ContentVersion, $_.ContentBuildVersion).ToLower()
    $index = $commons.IndexOf($props)
    if ($index -ge 0) {
        $result += [PSCustomObject]@{
            GameBuildVersion    = $_.GameBuildVersion
            OnlineVersion       = $_.OnlineVersion
            ContentVersion      = $_.ContentVersion
            ContentBuildVersion = $_.ContentBuildVersion        
            deploymentDirectory = $_.deploymentDirectory
            environmentname     = $deploy[$index].environmentname
        }
    }
}

# show the result (or export it to CSV or whatever)
$result

使用您提供的示例,这将产生:

GameBuildVersion    : 68858.zip
OnlineVersion       : 70793.zip
ContentVersion      : 68858.69165-1.zip
ContentBuildVersion : 69165-1.zip
deploymentDirectory : C:\deployer\script\deploy-AB
environmentname     : Staging35

【讨论】:

  • 这基本上就是我最终所做的。虽然我只是循环了 $deploys,并使用 $directory 作为参考数组进行了比较对象,匹配所有 4 个属性,并使用 passthru 保留额外的属性,以便我可以捕获它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多