我有两个大数组。一个是包含 100,000 个 PSCustomObjects 的数组(称为 Array1),每个对象都有一个名为“Token”的属性。而另一个数组只是一个字符串数组,第二个数组的大小为 2500 个元素。
面临的挑战是 Array1 的每个元素都需要与 Array2 中的所有元素进行检查并相应地标记。即,如果 Array1 中的 Token 值与 Array2 中的任何元素匹配,则将其标记为“找到匹配!”
循环实际上会使它变得非常慢。有一个更好的方法吗? P.S.: Array1 中的项也有序号属性,数组就是按照这个顺序排序的。
代码如下:
$Array1 = @()
$Array2 = @()
#Sample object:
$obj = New-Object -TypeName PSCustomObject
$obj | Add-Member -MemberType NoteProperty -Name Token -Value "SOMEVALUEHERE"
$obj | Add-Member -MemberType NoteProperty -Name TokenOrdinalNum -Value 1
$Array1 += $obj # This array has 100K such objects
$Array2 = @("VAL1", "SOMEVALUEHERE", ......) #Array2 has 2500 such strings.
此输出将需要是一个新的对象数组,例如“ArrayFinal”,它具有一个名为“MatchFound”的附加注释属性。
请帮忙。
答案 0 :(得分:0)
我会创建一个哈希表,以便从您的 $Array2
中的值进行快速查找。
为清楚起见,我将 $Array1
和 $Array2
重命名为 $objects
和 $tokens
。
# the object array
$objects = [PsCustomObject]@{ Token = 'SOMEVALUEHERE'; TokenOrdinalNum = 1 },
[PsCustomObject]@{ Token = 'VAL1'; TokenOrdinalNum = 123 },
[PsCustomObject]@{ Token = 'SomeOtherValue'; TokenOrdinalNum = 555 } # etcetera
# the array with token keywords to check
$tokens = 'VAL1', 'SOMEVALUEHERE', 'ShouldNotFindThis' # etcetera
# create a lookup Hashtable from the array of token values for FAST lookup
# you can also use a HashSet ([System.Collections.Generic.HashSet[string]]::new())
# see https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1
$lookup = @{}
$tokens | ForEach-Object { $lookup[$_] = $true } # it's only the Keys that matter, the value is not important
# now loop over the objects in the first array and check their 'Token' values
$ArrayFinal = foreach ($obj in $objects) {
$obj | Select-Object *, @{Name = 'MatchFound'; Expression = { $lookup.ContainsKey($obj.Token) }}
}
# output on screen
$ArrayFinal | Format-Table -AutoSize
# write to Csv ?
$ArrayFinal | Export-Csv -Path 'Path\To\MatchedObjects.csv' -NoTypeInformation
输出:
Token TokenOrdinalNum MatchFound
----- --------------- ----------
SOMEVALUEHERE 1 True
VAL1 123 True
SomeOtherValue 555 False
答案 1 :(得分:0)
100kb 对象并不太大。这是使用比较对象的示例。默认情况下,它会根据每个其他对象(919 毫秒)检查每个对象。编辑:好的,如果我更改 $b 的顺序,则需要更长的时间(13 分钟)。如果大多数位置最终相同,则首先对两个列表进行排序应该可以正常工作。(测量命令为 1.99 秒)。如果每个项目都偏离 1 个位置,它仍然需要很长时间($b = 1,$b)。
$a = foreach ($i in 1..100kb) { [pscustomobject]@{token = get-random} }
$a = $a | sort-object token
$b = $a.token | sort-object
compare-object $a.token $b -IncludeEqual
InputObject SideIndicator
----------- -------------
1507400001 ==
120471924 ==
28523825 ==
...