【问题标题】:Swapping array values with for and yield scala用 for 和 yield scala 交换数组值
【发布时间】:2012-04-26 20:31:13
【问题描述】:

我正在尝试使用 for 和 yield 交换数组中的每一对值,但到目前为止我非常不成功。我尝试过的如下:

val a = Array(1,2,3,4,5) //What I want is Array(2,1,4,3,5)

for(i<-0 until (a.length-1,2),r<- Array(i+1,i)) yield r

上面给出的sn-p返回向量2,1,4,3(5省略)

有人能指出我在这里做错了什么以及如何使用 for 和 yield 来获得正确的反转吗?

谢谢

【问题讨论】:

  • 这是来自“不耐烦的 Scala”。练习 3.2
  • 下次请提一下,这是一个家庭作业。

标签: scala for-loop iteration swap yield


【解决方案1】:

如果你不使用for/yield会更容易:

a.grouped(2)
  .flatMap{ 
    case Array(x,y) => Array(y,x)
    case Array(x) => Array(x)
  }.toArray // Array(2, 1, 4, 3, 5)

【讨论】:

  • 这大概是一种成熟的做事方式。我正在学习 scala,想知道是否可以使用 for/yield 完成相同的操作。
  • @sc_ray,for/yield 构造在很多时候让事情变得更好,但这并不是一个很好的匹配。
  • 如果原始任务来自 Horstman 的书,它要求我们交换 数组中的元素,而不是创建新元素。但是这些解决方案比 yield(ing) 更优雅
  • 抱歉,有两个任务:使用现有数组交换元素并创建新数组(使用地图功能)
【解决方案2】:
a.grouped(2).flatMap(_.reverse).toArray

或者如果您需要 for/yield(在这种情况下要简洁得多,实际上扩展为相同的代码):

(for {b <- a.grouped(2); c <- b.reverse} yield c).toArray

【讨论】:

  • 我喜欢使用reverse。不错。
  • 练习说做一个循环,然后做一个 for/yield,而不是一个功能解决方案。不过不错……
【解决方案3】:

我不知道 OP 是否正在为不耐烦的人阅读 Scala,但这是练习 3.3。

我喜欢地图解决方案,但我们还没有讨论那一章,所以这是我使用所需的 for/yield 的丑陋实现。您可能可以将一些 yield 逻辑移动到保护/定义中。

for( i <- 0 until(a.length,2); j <- (i+1).to(i,-1) if(j<a.length) ) yield a(j)

我是一个 Java 人,所以我无法确认这个断言,但我很好奇地图/分组和迭代器的开销是什么。我怀疑这一切都编译成相同的 Java 字节码。

【讨论】:

  • 不错。这似乎更符合练习的精神。
  • 很好地回答了这个问题。
【解决方案4】:

另一个简单的收益解决方案:

def swapAdjacent(array: ArrayBuffer[Int]) = {
    for (i <- 0 until array.length) yield (
        if (i % 2 == 0)
            if (i == array.length - 1) array(i) else array(i + 1)
        else array(i - 1)
    )
}

【讨论】:

    【解决方案5】:

    这是我的解决方案

      def swapAdjacent(a: Array[Int]):Array[Int] =
        (for(i <- 0 until a.length) yield
          if (i%2==0 && (i+1)==a.length) a(i) //last element for odd length
          else if (i%2==0) a(i+1)
          else a(i-1)
        ).toArray
    

    https://github.com/BasileDuPlessis/scala-for-the-impatient/blob/master/src/main/scala/com/basile/scala/ch03/Ex03.scala

    【讨论】:

      【解决方案6】:

      如果您正在为不耐烦的人在 Scala 中做练习 3.2 和 3.3,那么这两个都是我的答案。它们与移动的逻辑相同。

      /** Excercise 3.2 */
      for (i <- 0 until a.length if i % 2 == 1) {val t = a(i); a(i) = a(i-1); a(i-1) = t }
      /** Excercise 3.3 */
      for (i <- 0 until a.length) yield { if (i % 2 == 1) a(i-1) else if (i+1 <= a.length-1) a(i+1) else a(i) }
      

      【讨论】:

        【解决方案7】:
        for (i <- 0 until arr.length-1 by 2) { val tmp = arr(i); arr(i) = arr(i+1); arr(i+1) = tmp }
        

        我最近开始学习 Scala,Scala for the Impatient(第 1 版)一书的所有解决方案都可以在我的 github 上找到:

        第 2 章 https://gist.github.com/carloscaldas/51c01ccad9d86da8d96f1f40f7fecba7

        第 3 章 https://gist.github.com/carloscaldas/3361321306faf82e76c967559b5cea33

        【讨论】:

          【解决方案8】:

          我有我的解决方案,但没有收益。也许有人会发现它很有用。

          def swap(x: Array[Int]): Array[Int] = {
              for (i <- 0 until x.length-1 by 2){
                var left = x(i)
                x(i) = x(i+1)
                x(i+1) = left
              }
              x
            }
          

          【讨论】:

            【解决方案9】:

            假设数组不为空,请继续:

            val swapResult = for (ind <- arr1.indices) yield {
              if (ind % 2 != 0) arr1(ind - 1)
              else if (arr1(ind) == arr1.last) arr1(ind)
              else if (ind % 2 == 0) arr1(ind + 1)
            }
            

            【讨论】:

            • @jwvh 我发现很少有解决方案在奇数个变量的情况下抛出异常,因此修改已完成。我可以看到 fi 定义了一个空数组,而不是方法 .indices 可能会产生编译时错误。
            • .indices 在空的Array不会 产生编译时错误。它不会产生运行时错误。它工作正常,没有错误。
            • @jwvh 谢谢你刚刚想到,如果我们在声明期间没有定义数组的类型,即 val arr1: Array[] = Array() 那么 .indices 可以工作,但是当我们依赖于类型时推断即 val arr1 = Array() 则错误存在
            猜你喜欢
            • 2014-05-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-05-10
            • 2016-02-12
            • 1970-01-01
            • 1970-01-01
            • 2016-07-21
            相关资源
            最近更新 更多