简体   繁体   English

PowerShell 提高阵列更新性能

[英]PowerShell improve array update performance

I have two arrays with user details.我有两个带有用户详细信息的 arrays。

Array 1阵列 1

Let us say there are around 2000 different users, and they are present in the "Distinct Users" array.假设有大约 2000 个不同的用户,他们存在于“不同用户”数组中。 Distinct users is an array of user objects, with properties like:不同的用户是一组用户对象,具有如下属性:

$userDetailsObject=@{
    UserName = "UserName1"
    UserEmail = "UserEmail1"
    Category = "Category1"

} 

Array 2阵列 2

The second array is a list of all users that are part of multiple groups - named "All Group Users".第二个数组是属于多个组的所有用户的列表 - 名为“所有组用户”。 So there can be repetition of users, as the same user can be part of mutliple groups.因此可能存在重复用户,因为同一个用户可以是多个组的一部分。 The "All Group Users" array doesnt have the category detail of the users. “所有组用户”数组没有用户的类别详细信息。 There are around 12000 objects in this array.该数组中有大约 12000 个对象。

$groupUserDetailsObject=@{
    UserName = "UserName1"
    UserEmail = "UserEmail1"
    GroupName = "Group1"
    Category = ""

}

I am trying to get group wise user details with category, and need to compare "All Group Users" array and "Distinct Users" array ( based on the email address which will be unique), and update the Category property for the users in "All Group Users".我正在尝试使用类别获取组明智的用户详细信息,并且需要比较“所有组用户”数组和“不同用户”数组(基于 email 地址,该地址将是唯一的),并在“所有组用户”。

What will be the fastest way to do this?最快的方法是什么? I tried different combinatons like nested foreach loops and regex matches, but haven't been able to speed this up considerably, takes around 20 seconds to go through each user in the "Distinct Users" array and update all matching objects in the "All Group Users" array.我尝试了不同的组合,如嵌套的 foreach 循环和正则表达式匹配,但无法显着加快速度,通过“不同用户”数组中的每个用户到 go 大约需要 20 秒,并更新“所有组”中的所有匹配对象用户”数组。

Adding the mock code that I was using to test this out:添加我用来测试的模拟代码:

$Users=[System.Collections.ArrayList]@()
$a = @(1..12000)
$i=0

#build 12000 sample users with 2000 unique users by adding sample values
foreach ($item in $a)
{   
    if($i -eq 2000) #reset pattern after every 200 users
    {
        $i=0
    }
    $userDetailsObject=@{
        UserName = "UserName$i"
        UserEmail = "UserEmail$i"
        Category  = ""

    } 
    $obj = New-Object -Type PSObject -Prop $userDetailsObject
    $Users.Add($obj)
    $i++
}

#loop through 2000 unique users and compare by email address against 12000 users
for($i=0 ;$i -lt 2000 ;$i++)
{
    [regex] $regex = '(?i)^('+[regex]::escape("UserEmail$i") + ')$'

    Measure-Command {foreach($item in ($Users.where{$_.UserEmail -match $regex}))
    {
        $item.Category  = "Category$i"
    }
}| Select-Object -Property TotalSeconds

}

Thanks.谢谢。

If you need to compare fast, use a Hashtable to store the user objects in. This would mean every item in the hash must have a unique key , and for that you can use the users EmailAddress property (which in a network should be unique for each user).如果您需要快速比较,请使用 Hashtable 来存储用户对象。这意味着 hash 中的每个项目都必须有一个唯一的 key ,为此您可以使用 users 的 EmailAddress 属性(在网络中应该是唯一的每个用户)。

Something like:就像是:

Write-Host 'Creating dummy users'
# build a hashtable with 12000 sample users with unique email addresses (as in real life they would have)
$userHash = [ordered]@{}
foreach ($item in @(1..12000)) {
    $userHash["UserEmail$item"] = [PsCustomObject]@{
        UserName  = "UserName$item"
        UserEmail = "UserEmail$item"
        Category  = ""
    } 
}

Write-Host 'Setting Category on 2000 users'
Measure-Command {
    for($i = 0; $i -lt 2000; $i++) {
        if ($userHash.Contains("UserEmail$i")) {
            $userHash["UserEmail$i"].Category = "Category$i"
        }
    }
} | Select-Object -Property TotalSeconds

If you want to see the results如果你想看结果

$userHash.Values | Select-Object * | Format-Table

UPDATE更新

Thanks for adding extra explanation.感谢您添加额外的解释。 If I understand correctly, this is what you want to do:如果我理解正确,这就是你想要做的:

$distinctUsers = 2000
$allGroupUsers = 12000

Write-Host "Creating $distinctUsers DISTINCT users"
# build a hashtable with $distinctUsers sample users with unique email addresses
# this doesn't need to be an ordered list, it is just for lookup
$distinctHash = @{}
foreach ($i in @(1..$distinctUsers)) {
    $distinctHash["UserEmail$i"] = [PsCustomObject]@{
        UserName  = "UserName$i"
        UserEmail = "UserEmail$i"
        Category  = "Category$i"
    } 
}

Write-Host "Creating $allGroupUsers GROUP users"
# build a hashtable with $allGroupUsers sample users
# to have the output easier on the eyes, make this hash ordered
$groupHash = [ordered]@{}
for ($i = 1; $i -le $allGroupUsers; $i++) {
    # uniqify the key using the email addresses combined with the value of $i
    # reset the user counter on every $distinctUsers users
    $currentUser = (($i - 1) % $distinctUsers) + 1
    $uniqueEmail = '{0}-{1}' -f $i, "UserEmail$currentUser"
    $groupHash[$uniqueEmail] = [PsCustomObject]@{
        UserName  = "UserName$currentUser"
        UserEmail = "UserEmail$currentUser"
        GroupName = "Group$i"
        Category  = ""
    } 
}


Write-Host "Setting Category property on the $($groupHash.Count) GROUP users"
Measure-Command {
    foreach ($uniqueEmail in $groupHash.Keys) {
        $realEmail = ($uniqueEmail -split '-', 2)[-1]
        if ($distinctHash.ContainsKey($realEmail)) {
            $groupHash[$uniqueEmail].Category = $distinctHash[$realEmail].Category
        }
    }
} | Select-Object -Property TotalSeconds

After this, the $groupHash will be updated.在此之后,$groupHash 将被更新。
To see the result:要查看结果:

$groupHash.Values | Select-Object * | Format-Table -AutoSize

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM