New-FastLookup.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
function New-FastLookup {
    <#
    .SYNOPSIS
        Designed to optimize the speed of searching an array.
 
    .DESCRIPTION
        Improve the speed of looking up a value in an array by creating a hashtable index.
        Good for looping through very large arrays or CSV files
 
    .NOTES
        Version: 1.2
        Author: Miles Gratz
        Creation Date: April 20, 2017
        Purpose/Change: Improve examples
 
    .PARAMETER Array
        A mandatory parameter specifying input array used to create 'FastLookup'
 
    .PARAMETER Header
        An optional parameter specifying the header in the input array used to create 'FastLookup'
  
    .OUTPUTS
        A hashtable, listing the values in the array and their corresponding index
     
    .EXAMPLE
 
        PS>
     
        $array = 1..1000000
        $hashtable = New-FastLookup -Array $array
        Get-FastLookup -Value 2017 -Array $array -Table $hashtable
 
    .EXAMPLE
 
        PS>
 
        # Search for thousand random numbers in an array of one million
 
        $array = 1..1000000
        $search = 1..1000 | ForEach-Object {
            Get-Random -Maximum $array.Count
        }
 
        ---------------------------------------------------------------
         
        Where-Object Performance Test
 
        Measure-Command {
            $array | Where-Object { $_ -in $search }
        }
 
        Minutes : 2
        Seconds : 39
        Milliseconds : 658
 
        ---------------------------------------------------------------
 
        ForEach Performance Test
 
        Measure-Command {
            foreach ($item in $array){ if ($item -in $search){ $item } }
        }
 
        Minutes : 1
        Seconds : 27
        Milliseconds : 460
 
        ---------------------------------------------------------------
 
        FastLookup Performance Test
 
        Measure-Command {
            $hashtable = New-FastLookup -Array $array
            foreach ($item in $search){
                Get-FastLookup -Value $item -Array $array -Table $hashtable
            }
        }
 
        Minutes : 0
        Seconds : 49
        Milliseconds : 933
 
        ---------------------------------------------------------------
 
        [NOTE] Performance test on Windows 10 x64 (i5-6200U/8GB/SSD)
    #>


    param(
        [Parameter(Mandatory=$true)]
        [array]$Array,
        $Header
    )

    # Identify headers in input array
    $Headers = $Array | Get-Member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'
    
    # Define empty hashtable and index
    $HashTable = @{}
    $Index = 0
   
    #1: Header specified
    #2: Header exists in array
    If (($Header -ne $null) -and ($Header -in $Headers))
    {
        # Redefine array with only data from specified Header
        $Array = $Array.$Header
    }
    
    #1: Header is specified
    #2: Header does NOT exist in array
    ElseIf (($Header -ne $null) -and ($Header -notin $Headers))
    {
        # Exit function with error
        Write-Error "Specified header ($Header) does not exist in input array."
        Break
    }

    #1: Header is NOT specified
    #2: Array contains multiple Headers
    ElseIf (($Header -eq $null) -and ($Headers.Count -gt 1))
    {
        # Exit function with error
        Write-Error "Input array requires the -Header parameter (multiple columns detected)."
        Break
    }

    # Loop through array
    foreach ($Item in $Array)
    {
        # Add index of Item to hashtable
        # Name Value
        # ---- -----
        # Server1 953
        # Server2 1157
        Try
        {
            $HashTable.Add($Item,$Index)
        }

        # Duplicate key detected, add to existing value
        # Name Value
        # ---- -----
        # Server1 953
        # Server2 1157,3325
        Catch
        {       
            $HashTable[$Item] = ($HashTable[$Item],$Index -join ",")         
        }
        
        # Increment loop
        $Index++
    }
    
    # Output results
    $HashTable
}