Powershell - 针对另一个大数组的每个元素搜索大数组的每个元素

时间:2021-05-28 08:51:28

标签: powershell

我有两个大数组。一个是包含 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”的附加注释属性。

请帮忙。

2 个答案:

答案 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 ==
...