【问题标题】:Powershell even and odd numbersPowershell 偶数和奇数
【发布时间】:2022-02-10 09:50:37
【问题描述】:

它获取一个文件作为参数,我需要文件的偶数行和奇数行中的偶数和奇数之和

Input:
1 2 3 4 5
2 3 9 5
4 6 1
6 3 1 2 4
Output:
Sum of odd numbers:(1+3+5+1)=10
Sum of even numbers:(2+6+2+4)=12

我尝试使用 foreach 和不使用它,但我不知道如何将字符串从文件转换为整数并将其放入数组

【问题讨论】:

  • 家庭作业? ;-) 显示您已经尝试过的内容。我很确定我们可以为您提供更多帮助。
  • 这听起来很容易,但您是要分别求偶数行和奇数行,或者这些行上的数字,还是每行上的偶数/奇数。同时查看%(模数)运算符。这是测试偶数/奇数的典型方法。
  • @Steven >示例输出实际上解释了这一点。 ;-)
  • @enteo,也许你可以快速浏览一下How to Ask a Good Question。话虽如此,我会尝试从中获得一些乐趣。
  • @Steven > ...但我认为 OP 发布的示例输出实际上已经确定了这一点。 ;-) ... 没关系。我会等待是否有一些澄清。

标签: powershell


【解决方案1】:

这是一种方法。

下面的代码使用了输入文件的 Here-String 虚拟表示,但在现实生活中您会使用

$fileIn = Get-Content -Path 'Path\To\The\FileWithNumbers.txt'
$fileIn = @"
1 2 3 4 5
2 3 9 5
4 6 1
6 3 1 2 4
"@ -split '\r?\n'

$oddLine = $true            # first line is an odd line
$oddTotal, $evenTotal = 0   # create two variables to total the numbers
foreach ($line in $fileIn) {
    [int[]]$numbers = $line.Trim() -split '\s+'  # split on whitespace(s) and cast to [int]
    foreach ($n in $numbers) {
        if ($oddLine) {
            if ($n % 2) { $oddTotal += $n }
        }
        else {
            if (($n % 2) -eq 0) { $evenTotal += $n }
        }
    }
    $oddLine = !$oddLine # toggle odd and even line
}


"Sum of odd numbers in odd lines:   $oddTotal"
"Sum of even numbers in even lines: $evenTotal"

结果:

Sum of odd numbers in odd lines:   10
Sum of even numbers in even lines: 14

附注您的示例输出中有一个错误:2+6+2+4 等于 14,而不是 12 ;)


如果您的输出还需要显示添加的数字,您可以执行以下操作:

$oddLine = $true            # first line is an odd line
# create two collection objects to gather all the numbers
$oddNumbers  = [System.Collections.Generic.List[int]]::new()  
$evenNumbers = [System.Collections.Generic.List[int]]::new()
foreach ($line in $fileIn) {
    [int[]]$numbers = $line.Trim() -split '\s+'  # split on whitespace(s) and cast to [int]
    foreach ($n in $numbers) {
        if ($oddLine) {
            if ($n % 2) { $oddNumbers.Add($n) }
        }
        else {
            if (($n % 2) -eq 0) { $evenNumbers.Add($n) }
        }
    }
    $oddLine = !$oddLine # toggle odd and even line
}

# calculate the totals from the lists
$oddTotal  = ($oddNumbers | Measure-Object -Sum).Sum
$evenTotal = ($evenNumbers | Measure-Object -Sum).Sum

"Sum of odd numbers in odd lines:   $oddTotal ($($oddNumbers -join '+'))"
"Sum of even numbers in even lines: $evenTotal ($($evenNumbers -join '+'))"

结果:

Sum of odd numbers in odd lines:   10 (1+3+5+1)
Sum of even numbers in even lines: 14 (2+6+2+4)

【讨论】:

    【解决方案2】:

    我昨天写了这篇文章,但质疑这个问题是否是家庭作业,我最初不想发帖。也就是说,既然其他人正在研究它,我想我应该继续分享。

    $Numbers = @( Get-Content 'C:\temp\numbers.txt' )
    $EvenOdd = @{ 0 = 'even'; 1 = 'odd' }
    
    For( $i = 0; $i -lt $Numbers.Count; ++$i )
    {    
        $LineOdd = $i % 2
        $Sum =
        $Numbers[$i].Trim() -Split "\s+" |
        Where-Object{ $_ % 2 -eq $LineOdd } |
        Measure-Object -Sum |
        Select-Object -ExpandProperty Sum
    
        "Line {0} : Sum of {1} numbers:({2})={3}" -f $i, ($EvenOdd[$LineOdd]), ($NumberArray -Join '+'), $Sum
    }
    

    结果:

    Line 0 : Sum of even numbers:(2+4)=6
    Line 1 : Sum of odd numbers:(3+9+5)=17
    Line 2 : Sum of even numbers:(4+6)=10
    Line 3 : Sum of odd numbers:(3+1)=4
    

    考虑第一行 Line#1 的一些小调整:

    $Numbers = @( Get-Content 'C:\temp\numbers.txt' )
    $EvenOdd = @{ 0 = 'even'; 1 = 'odd' }
    
    For( $i = 1; $i -le $Numbers.Count; ++$i )
    {    
        $LineOdd = $i % 2
        $Sum =
        $Numbers[$i-1] -Split "\s+" |
        Where-Object{ $_ % 2 -eq $LineOdd } |
        Measure-Object -Sum |
        Select-Object -ExpandProperty Sum
    
        "Line {0} : Sum of {1} numbers:({2})={3}" -f $i, ($EvenOdd[$LineOdd]), ($NumberArray -Join '+'), $Sum
    }
    

    注意:我最初是在常规空间上拆分的。我将空格的想法和.Trim()Theo's example 分开。我没有打扰到[int]

    注意:这些示例无法与Theo's answer 进行比较。很明显,我们对这个问题的解释不同。如果我有时间,我会研究另一种解释。


    分别对奇偶行中的所有数字进行交替求和:

    $Numbers     = @( Get-Content 'C:\temp\numbers.txt' )
    $EvenNumbers = [System.Collections.Generic.List[int]]::new()
    $OddNumbers  = [System.Collections.Generic.List[int]]::new()
    
    For( $i = 1; $i -le $Numbers.Count; ++$i )
    {
        $LineOdd = $i % 2
        $NumberHash =
        $Numbers[$i-1].Trim() -Split "\s+" |
        Group-Object { $_ % 2 } -AsHashTable
    
        Switch ($LineOdd) 
        {
            0 { $NumberHash[0].foreach( { $EvenNumbers.Add($_) } ); Break }
            1 { $NumberHash[1].foreach( { $OddNumbers.Add($_) }  ); Break }
        }
    }
    
    $SumEven = ($EvenNumbers | Measure-Object -Sum).Sum
    $SumOdd  = ($OddNumbers | Measure-Object -Sum ).Sum
    
    "Sum of odd lines  : {0}{1}" -f "($($OddNumbers -join '+'))=",$SumOdd
    "Sum of even lines : {0}{1}" -f "($($EvenNumbers -join '+'))=", $SumEven
    

    回想起来,用ForEach-Object{} 代替Group-ObjectSwitch 也同样有效,所以我添加了另一个示例:

    $Numbers     = @( Get-Content 'C:\temp\numbers.txt' )
    $EvenNumbers = [System.Collections.Generic.List[int]]::new()
    $OddNumbers  = [System.Collections.Generic.List[int]]::new()
    
    For( $i = 1; $i -le $Numbers.Count; ++$i )
    {
        $LineOdd = $i % 2
        $Numbers[$i-1].Trim() -Split "\s+" |
        ForEach-Object{
            If( !$LineOdd -and $_ % 2 -eq 0 ) {
                $EvenNumbers.Add($_)
            }
            Elseif( $LineOdd -and $_ % 2 -eq 1 ) {
                $OddNumbers.Add($_)
            }
        }
    }
    
    $SumEven = ($EvenNumbers | Measure-Object -Sum).Sum
    $SumOdd  = ($OddNumbers | Measure-Object -Sum ).Sum
    
    "Sum of odd lines  : {0}{1}" -f "($($OddNumbers -join '+'))=",$SumOdd
    "Sum of even lines : {0}{1}" -f "($($EvenNumbers -join '+'))=", $SumEven
    

    还有一个比上一个更高效、更雄辩的版本:

    $Numbers = @( Get-Content 'C:\temp\numbers.txt' )
    
    $Sum = @{
        0 = [System.Collections.Generic.List[int]]::new()
        1 = [System.Collections.Generic.List[int]]::new()
    }
    
    For( $i = 1; $i -le $Numbers.Count; ++$i )
    {
        $LineOdd = $i % 2    
        $Numbers[$i-1].Trim() -Split "\s+" |
        ForEach-Object{ 
            If( $_ % 2 -eq $LineOdd ) {
                $Sum[$LineOdd].Add($_) 
            }
        }
    }
    
    $SumOdd  = ($Sum[1] | Measure-Object -Sum).Sum
    $SumEven = ($Sum[0] | Measure-Object -Sum).Sum
    
    "Sum of odd lines  : {0}{1}" -f "($($Sum[0] -join '+'))=", $SumOdd
    "Sum of even lines : {0}{1}" -f "($($Sum[1] -join '+'))=", $SumEven
    

    所以,这是一个改进,因为它只需要循环内的单个 If 语句。它还可以防止大量的模数计算。在前面的示例中,每次ElseIf 触发时,我都会有一个If/ElseIf ergo,会发生第二次模数计算。当然,我可以预先计算一个变量,但这不会完全删除Else...。通过将集合存储在哈希中,只需进行简单的比较即可知道要附加哪个集合。

    注意:最后 3 个示例从第 1 行开始,并认为第 1 行是奇数。与第 0 行相反...

    【讨论】:

      【解决方案3】:

      我想我也会发布我对这个问题的解决方案,暂时不想这样做,因为我认为这是家庭作业,但既然已经有 2 个答案,而且我已经有了代码......

      代码与Theo's answer非常相似。

      using namespace System.Collections.Generic
      using namespace System.Linq
      
      $i = $false
      $oddArray = [list[int]]::new()
      $evenArray = [list[int]]::new()
      
      foreach($line in $array) {
          $numbers = $line -split '\s+'
          if($i = -not $i) {
              # Odd Lines
              foreach($number in $numbers) {
                  # If this number is Odd
                  if($number % 2) {
                      $oddArray.Add($number)
                  }
              }
              continue
          }
          #Even Lines
          foreach($number in $numbers) {
              # If this number is even
              if(-not ($number % 2)) {
                  $evenArray.Add($number)
              }
          }
      }
      
      [string]::Format(
          "Sum of odd numbers: ({0}) = {1}",
          ($oddArray -join ' + '),
          [Enumerable]::Sum($oddArray)
      )
      [string]::Format(
          "Sum of even numbers: ({0}) = {1}",
          ($evenArray -join ' + '),
          [Enumerable]::Sum($evenArray)
      )
      

      【讨论】:

      • +1 是一种非常酷的交替方式,似乎没有明确这样做。诚然,我在这个方面做得过火了,但我觉得模数很酷。更不用说为Group-Object 寻找位置而进行的富有成效的斗争。看看this somewhat similar QA 我在哪里冒犯了。另外,我在这里的答案中添加了最后一个非常酷的示例。检查一下,让我知道你的想法。谢谢!
      • 谢谢@Steven,我已经得到了你的回答,就像西奥的回答一样,哈哈。显示的所有示例都非常好,您确实付出了很大的努力来回答我认为不值得回答的帖子。当一个人看到回答问题的努力被忽视时感觉很糟糕:P
      【解决方案4】:

      看看其他人,我觉得可以简化字符串生成。还使用(滥用?)Powershell 动态转换。一些谷歌研究(包括随机的其他页面)提供了灵感和有用的信息。

      #read input, split on any whitespace
      $inputFile = (Get-Content "C:\temp\numbers.txt") -split "\s"
      
      #generate odds and evens arrays.
      $inputFile | foreach{ if($_ % 2 -eq 0) {$evens += $_} else{$odds += $_}}
      
      #make output strings
      "Sum of odd numbers:(" + ($odds -join '+') + ")=" + (($odds|Measure-Object -Sum).Sum)
      "Sum of even numbers:(" + ($evens -join '+') + ")=" + (($evens|Measure-Object -Sum).Sum)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多