From 830ed3d5f9252f8f2558461899b1286126a55099 Mon Sep 17 00:00:00 2001 From: Eugene Samoylov Date: Sun, 17 Nov 2019 21:12:59 +0500 Subject: [PATCH 1/3] Add `-Shuffle` switch to Get-Random command --- .../commands/utility/GetRandomCommand.cs | 58 +++++++++++++------ .../Get-Random.Tests.ps1 | 14 ++++- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs index 9ff9a933604..e895879af09 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 ShuffleSet = "ShuffleSet"; 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.Equals(GetRandomCommand.RandomListItemParameterSet, StringComparison.OrdinalIgnoreCase) || + ParameterSetName.Equals(GetRandomCommand.ShuffleSet, StringComparison.OrdinalIgnoreCase)) { _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 = ShuffleSet, 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 + + /// + /// If specified, then the command will return all input objects in randomized order + /// + [Parameter(ParameterSetName = ShuffleSet, 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 == ShuffleSet) { - // (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..891aff6d906 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,18 @@ 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[0] | Should -BeIn 1, 2, 3, 5, 8, 13 + $randomNumber[1] | Should -BeIn 1, 2, 3, 5, 8, 13 + $randomNumber[2] | Should -BeIn 1, 2, 3, 5, 8, 13 + $randomNumber[3] | Should -BeIn 1, 2, 3, 5, 8, 13 + $randomNumber[4] | Should -BeIn 1, 2, 3, 5, 8, 13 + $randomNumber[5] | Should -BeIn 1, 2, 3, 5, 8, 13 + $randomNumber[6] | Should -BeNullOrEmpty + } + It "Should return for a string collection " { $randomNumber = Get-Random -InputObject "red", "yellow", "blue" $randomNumber | Should -Be ("red" -or "yellow" -or "blue") @@ -173,7 +185,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 From ce35e202098692692afda6242eba7fa91b020067 Mon Sep 17 00:00:00 2001 From: Eugene Samoylov Date: Sun, 17 Nov 2019 21:59:29 +0500 Subject: [PATCH 2/3] Fix CodeFactor issue --- .../commands/utility/GetRandomCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs index e895879af09..6bc14ad3985 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs @@ -296,7 +296,7 @@ private double ConvertToDouble(object o, double defaultIfNull) #region Shuffle parameter /// - /// If specified, then the command will return all input objects in randomized order + /// If specified, then the command will return all input objects in randomized order. /// [Parameter(ParameterSetName = ShuffleSet, Mandatory = true)] public SwitchParameter Shuffle { get; set; } From fe68cf6a48eb771f53c427f90510409c7c7c3e23 Mon Sep 17 00:00:00 2001 From: Eugene Samoylov Date: Mon, 18 Nov 2019 10:26:46 +0500 Subject: [PATCH 3/3] Fix the review issues --- .../commands/utility/GetRandomCommand.cs | 14 +++++++------- .../Get-Random.Tests.ps1 | 8 +------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs index 6bc14ad3985..c228b42c088 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs @@ -28,7 +28,7 @@ public class GetRandomCommand : PSCmdlet private const string RandomNumberParameterSet = "RandomNumberParameterSet"; private const string RandomListItemParameterSet = "RandomListItemParameterSet"; - private const string ShuffleSet = "ShuffleSet"; + private const string ShuffleParameterSet = "ShuffleParameterSet"; private static readonly object[] _nullInArray = new object[] { null }; private enum MyParameterSet @@ -51,8 +51,8 @@ private MyParameterSet EffectiveParameterSet { _effectiveParameterSet = MyParameterSet.RandomListItem; } - else if (ParameterSetName.Equals(GetRandomCommand.RandomListItemParameterSet, StringComparison.OrdinalIgnoreCase) || - ParameterSetName.Equals(GetRandomCommand.ShuffleSet, StringComparison.OrdinalIgnoreCase)) + else if (ParameterSetName == GetRandomCommand.RandomListItemParameterSet + || ParameterSetName == GetRandomCommand.ShuffleParameterSet) { _effectiveParameterSet = MyParameterSet.RandomListItem; } @@ -278,7 +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 = ShuffleSet, 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; } @@ -296,9 +296,9 @@ private double ConvertToDouble(object o, double defaultIfNull) #region Shuffle parameter /// - /// If specified, then the command will return all input objects in randomized order. + /// Gets or sets whether the command should return all input objects in randomized order. /// - [Parameter(ParameterSetName = ShuffleSet, Mandatory = true)] + [Parameter(ParameterSetName = ShuffleParameterSet, Mandatory = true)] public SwitchParameter Shuffle { get; set; } #endregion @@ -506,7 +506,7 @@ protected override void ProcessRecord() { if (EffectiveParameterSet == MyParameterSet.RandomListItem) { - if (ParameterSetName == ShuffleSet) + if (ParameterSetName == ShuffleParameterSet) { // this allows for $null to be in an array passed to InputObject foreach (object item in InputObject ?? _nullInArray) 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 891aff6d906..09f8e8f4bea 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Random.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Random.Tests.ps1 @@ -159,13 +159,7 @@ Describe "Get-Random" -Tags "CI" { 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[0] | Should -BeIn 1, 2, 3, 5, 8, 13 - $randomNumber[1] | Should -BeIn 1, 2, 3, 5, 8, 13 - $randomNumber[2] | Should -BeIn 1, 2, 3, 5, 8, 13 - $randomNumber[3] | Should -BeIn 1, 2, 3, 5, 8, 13 - $randomNumber[4] | Should -BeIn 1, 2, 3, 5, 8, 13 - $randomNumber[5] | Should -BeIn 1, 2, 3, 5, 8, 13 - $randomNumber[6] | Should -BeNullOrEmpty + $randomNumber | Should -BeIn 1, 2, 3, 5, 8, 13 } It "Should return for a string collection " {