# encoding: ascii # api: powershell # title: Select-Random # description: Select a user-defined number of random elements from the collection … which can be passed as a parameter or input via the pipeline. An improvement over http://www.powershellcentral.com/scripts/60 which allows you to select more than one item, and doesn’t copy the full collection into RAM. # version: 2.0 # type: script # author: Joel Bennett # license: CC0 # x-poshcode-id: 81 # x-derived-from-id: 83 # x-archived: 2009-01-06T14:32:58 # # # --------------------------------------------------------------------------- ### param([int]$count=1, [array]$inputObject=$null) BEGIN { if ($args -eq '-?') { @" Usage: Select-Random [[-Count] ] [-inputObject] (from pipeline) [-?] Parameters: -Count : The number of elements to select. -Collection : The collection from which to select a random element. -? : Display this usage information and exit Examples: PS> $arr = 1..5; Select-Random $arr PS> 1..10 | Select-Random -Count 2 "@ exit } elseif ($inputObject) { ### If you're accepting $args, you need to pass those in... # Write-Output $io | &($MyInvocation.InvocationName) $args; Write-Output $inputObject | &($MyInvocation.InvocationName) -Count $count break; } else { $seen = 0 $selected = new-object object[] $count $rand = new-object Random } } PROCESS { if($_) { $seen++ if($seen -lt $count) { $selected[$seen-1] = $_ } ## For each input element $n there is a $count/$n chance that it becomes part of the result. elseif($rand.NextDouble() -gt $count/$seen) { ## For the ones previously selected, there's a 1/$n chance of it being replaced $selected[$rand.Next(0,$count)] = $_ } } } END { if (-not $inputObject) { ## DO ONCE: (only on the re-invoke, not when using -inputObject) Write-Verbose "Selected $count of $seen elements" Write-Output $selected # foreach($el in $selected) { Write-Output $el } } }