查找数组中重复项的代码,Scala

时间:2018-10-13 10:29:53

标签: arrays scala duplicates

我正在尝试构建一种可以在不使用任何预先实现的功能(例如“ sort”等)的情况下在数组中查找重复项的算法。

我没有错误,但是我的功能无法正常工作……您知道为什么吗? (我只是开始Scala编程)

def duplicate(s: Array[Int], length: Int): Boolean = {
  var i = 0 // start counting at value 0
  var j = 0
  var result:Boolean = false
  var isDupli:Boolean = false
  while(j < length && result == false) {
    if (s(i) == s(j)) {
      isDupli = true
      result = true
    }
    j += 1
  }

  result
}

var myArray = Array(2,2,2,2)
duplicate(Array(2,2), 2)

我在线找到了一些代码,但是人们正在使用函数排序。我的目标是滚动数组以查找任何重复项...

2 个答案:

答案 0 :(得分:2)

对您的代码的一些观察:

  • 您仅查看第一个(第0个)元素,而不会递增i,因此您无需检查任何后续元素是否重复。
  • length参数是多余的,因为我们可以通过Array(或s)属性来发现.length.size的长度。使用.length属性更安全,因为它始终有效。例如,duplicate(Array(1, 2, 3, 4, 5, 3), 10)会导致异常(java.lang.ArrayIndexOutOfBoundsException),因为数组没有10个成员。
  • 您将j初始化为与i相同的值,然后比较s(i) == s(j),因此即使没有第一个元素,也总是要获取第一个元素的重复项数组中的重复项。
  • 您返回result(指示您是否找到了结果),而不是isDupli(指示您是否找到了重复结果)。幸运的是,我们只需要其中之一,因为找到结果与找到重复项相同。

这是解决这些问题并简化某些代码的另一个版本:

def duplicate(s: Array[Int]): Boolean = {

  val length = s.length

  var i = 0 // start counting at value 0
  var foundDuplicate = false // Type inference means Scala knows this is Boolean

  // Loop through each member until we've found a duplicate.
  //
  // Note that "!foundDuplicate" is the same as "foundDuplicate == false"
  while(i < length && !foundDuplicate) { 

    // Now compare to each of the remaining elements. Start at the element above i.
    var j = i + 1

    // Loop through each of the remaining elements.
    while(j < length && !foundDuplicate) {

      // If we find a match, we're done.
      if (s(i) == s(j)) {
        foundDuplicate = true
      }

      // Look at the next j
      j += 1
    }

    // Look at the next i
    i += 1
  }

  // Return the result. If we didn't find anything, this will still be false.
  foundDuplicate
}

val myArray1 = Array(1, 2, 3, 4, 5, 6, 2, 8, 9)
val myArray2 = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
duplicate(myArray1)  // Returns true
duplicate(myArray2)  // Returns false

但是,尽管这完全是 procedural 代码,但在 Scala 中,我们可以使用更好的 functional 样式。 (过程代码使用var s,while循环等,在 Scala 中不受欢迎。)

import scala.annotation.tailrec

def duplicate(s: Array[Int]): Boolean = {

  // Helper function to search the array for matches to element at i
  @tailrec // Indicates function is tail recursive.
  def matchElement(i: Int): Boolean = {

    // Helper function to search for a match in remainder of array.
    @tailrec
    def matchRem(j: Int): Boolean = {

      // If j has reached the end of the array, we had no match.
      if(j >= s.length) false

      // Otherwise, does this element match the target? Match found.
      else if (s(i) == s(j)) true

      // Otherwise, look at the next element after j.
      else matchRem(j + 1) // Recursive call
    }

    // If this is the last character of the array, then we can't have a match.
    if(i >= s.length - 1) false

    // Otherwise did we find a duplicate in the remainder of this array?
    else if(matchRem(i + 1)) true

    // Otherwise, perform another iteration looking at the next element.
    else matchElement(i + 1) // Recursive call
  }

  // Start the ball rolling by looking at for duplicates of the first character.
  matchElement(0)
}

乍一看,这看起来可能很复杂,但是请注意,它没有任何 var声明或while循环。当然,这是一个自己动手的解决方案。使用其他Array函数可以更简单地实现这一目标。

答案 1 :(得分:-1)

在您的代码中,变量isDupli无用,因为无论如何您都返回result布尔变量。另外,您不会递增变量i。您可以如下使用for loop

 def duplicate(s: Array[Int], length: Int): Boolean ={
    var result:Boolean = false; val r = Range(0,length)
    for(i<-r;j<-(i+1) until length; if(s(i)==s(j))) result = true
    result
  }

在Scala REPL中:

scala> duplicate(Array(2,2),2)
res4: Boolean = true

scala> duplicate(Array(2,3),2)
res5: Boolean = false

scala> duplicate(Array(2,3,2),3)
res6: Boolean = true

scala> duplicate(Array(2,3,4),3)
res7: Boolean = false