diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs index 9ff9a933604..c228b42c088 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs @@ -28,6 +28,7 @@ public class GetRandomCommand : PSCmdlet private const string RandomNumberParameterSet = "RandomNumberParameterSet"; private const string RandomListItemParameterSet = "RandomListItemParameterSet"; + private const string ShuffleParameterSet = "ShuffleParameterSet"; private static readonly object[] _nullInArray = new object[] { null }; private enum MyParameterSet @@ -50,7 +51,8 @@ private MyParameterSet EffectiveParameterSet { _effectiveParameterSet = MyParameterSet.RandomListItem; } - else if (ParameterSetName.Equals(GetRandomCommand.RandomListItemParameterSet, StringComparison.OrdinalIgnoreCase)) + else if (ParameterSetName == GetRandomCommand.RandomListItemParameterSet + || ParameterSetName == GetRandomCommand.ShuffleParameterSet) { _effectiveParameterSet = MyParameterSet.RandomListItem; } @@ -276,6 +278,7 @@ private double ConvertToDouble(object o, double defaultIfNull) /// List from which random elements are chosen. /// [Parameter(ParameterSetName = RandomListItemParameterSet, ValueFromPipeline = true, Position = 0, Mandatory = true)] + [Parameter(ParameterSetName = ShuffleParameterSet, ValueFromPipeline = true, Position = 0, Mandatory = true)] [System.Management.Automation.AllowNull] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public object[] InputObject { get; set; } @@ -283,12 +286,23 @@ private double ConvertToDouble(object o, double defaultIfNull) /// /// Number of items to output (number of list items or of numbers). /// - [Parameter] + [Parameter(ParameterSetName = RandomNumberParameterSet)] + [Parameter(ParameterSetName = RandomListItemParameterSet)] [ValidateRange(1, int.MaxValue)] public int Count { get; set; } = 1; #endregion + #region Shuffle parameter + + /// + /// Gets or sets whether the command should return all input objects in randomized order. + /// + [Parameter(ParameterSetName = ShuffleParameterSet, Mandatory = true)] + public SwitchParameter Shuffle { get; set; } + + #endregion + #region Cmdlet processing methods private double GetRandomDouble(double minValue, double maxValue) @@ -492,29 +506,39 @@ protected override void ProcessRecord() { if (EffectiveParameterSet == MyParameterSet.RandomListItem) { - // this allows for $null to be in an array passed to InputObject - foreach (object item in InputObject ?? _nullInArray) + if (ParameterSetName == ShuffleParameterSet) { - // (3) - if (_numberOfProcessedListItems < Count) + // this allows for $null to be in an array passed to InputObject + foreach (object item in InputObject ?? _nullInArray) { - Debug.Assert(_chosenListItems.Count == _numberOfProcessedListItems, "Initial K elements should all be included in chosenListItems"); _chosenListItems.Add(item); } - else + } + else + { + foreach (object item in InputObject ?? _nullInArray) { - Debug.Assert(_chosenListItems.Count == Count, "After processing K initial elements, the length of chosenItems should stay equal to K"); - - // (1) - if (Generator.Next(_numberOfProcessedListItems + 1) < Count) + // (3) + if (_numberOfProcessedListItems < Count) { - // (2) - int indexToReplace = Generator.Next(_chosenListItems.Count); - _chosenListItems[indexToReplace] = item; + Debug.Assert(_chosenListItems.Count == _numberOfProcessedListItems, "Initial K elements should all be included in chosenListItems"); + _chosenListItems.Add(item); + } + else + { + Debug.Assert(_chosenListItems.Count == Count, "After processing K initial elements, the length of chosenItems should stay equal to K"); + + // (1) + if (Generator.Next(_numberOfProcessedListItems + 1) < Count) + { + // (2) + int indexToReplace = Generator.Next(_chosenListItems.Count); + _chosenListItems[indexToReplace] = item; + } } - } - _numberOfProcessedListItems++; + _numberOfProcessedListItems++; + } } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Random.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Random.Tests.ps1 index fa835478e98..09f8e8f4bea 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Random.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Random.Tests.ps1 @@ -156,6 +156,12 @@ Describe "Get-Random" -Tags "CI" { $randomNumber[6] | Should -BeNullOrEmpty } + It "Should return all the numbers for array of 1,2,3,5,8,13 in randomized order when the Shuffle switch is used" { + $randomNumber = Get-Random -InputObject 1, 2, 3, 5, 8, 13 -Shuffle + $randomNumber.Count | Should -Be 6 + $randomNumber | Should -BeIn 1, 2, 3, 5, 8, 13 + } + It "Should return for a string collection " { $randomNumber = Get-Random -InputObject "red", "yellow", "blue" $randomNumber | Should -Be ("red" -or "yellow" -or "blue") @@ -173,7 +179,7 @@ Describe "Get-Random" -Tags "CI" { $firstRandomNumber | Should -Not -Be $secondRandomNumber } - It "Should return the same number for hexadecimal number and regular number when the switch SetSeed it used " { + It "Should return the same number for hexadecimal number and regular number when the switch SetSeed is used " { $firstRandomNumber = Get-Random 0x07FFFFFFFF -SetSeed 20 $secondRandomNumber = Get-Random 34359738367 -SetSeed 20 $firstRandomNumber | Should -Be @secondRandomNumber