I'm solving the problem
here is the solution i made first
using namespace System.Linq
$DebugPreference = "Continue"
class kata{
static [string] FirstNonRepeatingLetter ([String]$string_){
[Enumerable]::GroupBy([char[]]$string_, [func[char, char]]{$args[0]}).Foreach{
if ($_.Count -eq 1){
Write-Debug ($_.key)
return $_.Key
}
}
return "~~~"
}
}
Write-Debug ([kata]::FirstNonRepeatingLetter("stress"))
it's return
DEBUG: t
DEBUG: r
DEBUG: e
DEBUG: ~~~
this is not what i expected I try this
using namespace System.Linq
$DebugPreference = "Continue"
class kata{
static [string] FirstNonRepeatingLetter ([String]$string_){
$groups = [Enumerable]::GroupBy([char[]]$string_, [func[char, char]]{$args[0]})
foreach ($group in $groups)
{
if ($group.Count -eq 1){
return $group.Key
}
}
return "~~~"
}
}
Write-Debug ([kata]::FirstNonRepeatingLetter("stress"))
and then what I wanted to see
DEBUG: t
and now I don't understand why these codes work differently...
You're executing return inside a script block ({ ... }) you've passed to the .ForEach() array method method:
In script blocks passed as arguments (as opposed to blocks that are integral to statements such as if and foreach), return exits only the block itself.
Therefore, your .ForEach() enumeration continues after each return; that is, while execution inside the script block is terminated, execution continues with the next .ForEach() iteration.
There actually is no direct way to stop the enumeration of .ForEach() (by contrast, the related .Where() array method has an optional parameter that accepts a 'First' to stop enumerating after finding the first match).
You have two options:
Set a Boolean flag inside your script block to indicate whether a result has been found, and exit the script block right away if the flag is found to be set.
Use a dummy loop so that you can repurpose a break statement to break out of the loop and thereby also out of the .ForEach() enumeration.
break would be looking up the entire call stack for a loop to break out of; if it finds none, execution would terminate overall - see this answer for more information.Either way, you need a return statement outside to script block in order to return a value from your class method.
Here's how to implement the dummy-loop approach:
using namespace System.Linq
$DebugPreference = 'Continue'
class kata{
static [string] FirstNonRepeatingLetter ([String]$string_){
$result = '~~~'
do { # dummy loop
[Enumerable]::GroupBy([char[]]$string_, [func[char, char]]{$args[0]}).Foreach{
if ($_.Count -eq 1){
Write-Debug ($_.key)
$result = $_.Key
break # break out of the dummy loop
}
}
} while ($false)
return $result
}
}
Write-Debug ([kata]::FirstNonRepeatingLetter('stress'))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With