PatrikJ
PatrikJ

Reputation: 2398

Searching for info in large arrays

I've got a script which indexes information from our equipment. To store and analyze the information I've created a class:

Add-Type @'
public class CPObject
{
    public int id;
    public string name;
    public string displayname;
    public string classname;
    public string ip;
    public string netmask;
    public string ManagementServer;
}
'@

Then when I run the script I've been planning to go through the object class to translate name to IP with the following function:

Function NameToIP {

    Param([int]$id=0, [string]$name="")

    $CPObject = $CPNetworkObjects | Where-Object { $_.id -eq $id -and $_.name -eq $name }

    If($CPObject.count -eq 1){
        $CPObject.ip
    } else {
        ""
    }
}

It works, but it's terribly slow as the $CPNetworkObjects contains over 12 000 elements of the type CPObject.

I want to speed this up. Is there any way to index an array to make the search more efficient or is the only solution to try to lessen the number of objects used?

Kind regards, Patrik

Upvotes: 0

Views: 1397

Answers (3)

mjolinor
mjolinor

Reputation: 68341

If any give combination of id plus name is unique, you can speed up a name-to-ip resolution by building a lookup table:

$NameToIP = @{}

Foreach ($Object in $Array) { $NameToIP["$($Object.id)_$($Object.Name)"] = $Object.ip }

Function NameToIP {

    Param([int]$id=0, [string]$name="")

    $NameToIP["$id_$name"]

 }

Upvotes: 3

Alvein
Alvein

Reputation: 141

Is there any way to index an array to make the search more efficient

First of all, I don't know a thing about powershell so I won't be able to give you code samples.

If you can change your data structure

If either the id or name is unique, you should try to remove this unique field from your CPObject and use it as the key for your hash map, and have your CPObject as the value returned by the hash table.

If you cannot change your data structure

You should try to sort your array using the name and/or the id You can go from O(n) time complexity O(log(n)) when looking for a name to

Hope this helped,

Upvotes: 0

Loïc MICHEL
Loïc MICHEL

Reputation: 26170

maybe you could use a pscustomobject instead of a class ? searching an array of 15000 simple objects doesnt seem too long :

PS>(1..15000) |%{                                                         
>>> $res+=new-object pscustomobject -property @{"id"=$_;name=(get-random)}
>>> }                                                                     

PS> measure-command -expression {$res |?{$_.id -eq 14999 -and $_.name -eq 513658722}} 

takes 802ms

Upvotes: 1

Related Questions