返回不像我期望的那样

Але*_*нов 3 linq powershell

我正在解决问题

这是我首先提出的解决方案

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"))
Run Code Online (Sandbox Code Playgroud)

回来了

DEBUG: t
DEBUG: r
DEBUG: e
DEBUG: ~~~
Run Code Online (Sandbox Code Playgroud)

这不是我所期望的 我试试这个

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"))
Run Code Online (Sandbox Code Playgroud)

然后是我想看的

DEBUG: t
Run Code Online (Sandbox Code Playgroud)

现在我不明白为什么这些代码的工作方式不同......

mkl*_*nt0 6

您正在传递给数组方法方法return脚本块( { ... }) 中执行:.ForEach()

  • 在作为参数传递的脚本块中(而不是像if和这样的语句的组成部分foreach),return 只退出块本身

  • 因此,您的.ForEach()枚举在 each 之后继续return;也就是说,当脚本块的执行终止时,执行继续进行下.ForEach()一次迭代。

实际上没有直接的方法来停止枚举.ForEach()(相比之下,相关的.Where()数组方法有一个可选参数,它接受一个'First' 以在找到第一个匹配项后停止枚举)。

您有两个选择:

  • 在您的脚本块内设置一个布尔标志以指示是否已找到结果,如果发现该标志已被设置,则立即退出脚本块。

    • 这样做的明显缺点是枚举总是运行到完成。
  • 使用虚拟循环,以便您可以重新调整break语句的用途以跳出循环,从而也跳出.ForEach()枚举。

    • 注意:如果没有虚拟循环,break将在整个调用堆栈中查找要跳出的循环;如果没有找到,则执行将整体终止-有关更多信息,请参阅此答案
  • 无论哪种方式,您都需要脚本块之外使用一个return语句,以便从您的类 method返回一个值。

以下是如何实现虚拟循环方法:

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'))
Run Code Online (Sandbox Code Playgroud)