1

I'm trying to build a algorithm that can find duplicates in an array, without Using any pre-implemented functions such as "sort" etc.

I have no error but my function does not work… Do you have any idea why? (I'm just starting Scala programming)

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)

I found some code online but people are Using the function sort. My goal is to scroll through the array to find for any duplicates...

Mike Allen
  • 8,139
  • 2
  • 24
  • 46
  • You never increment i so you are only ever comparing the first value to the other values – Karan Shishoo Oct 13 '18 at 10:33
  • I understand thank you! But the problem is that I can't even see the result for the first scan of the array. Result = true would not appear... – Data_Gengar Oct 13 '18 at 10:36
  • Oh it works. I'm sorry for disturbing. I will try to delete this topic! Thanks! – Data_Gengar Oct 13 '18 at 10:38
  • Possible duplicate of [How to find duplicates in a list?](https://stackoverflow.com/questions/24729544/how-to-find-duplicates-in-a-list) – Raman Mishra Oct 13 '18 at 12:29
  • 1
    you can use list.groupBy(identity) that way you will get the count of each element in the list which has more than one it has duplicates. – Raman Mishra Oct 13 '18 at 12:30
  • What exactly do you mean by *"will **try** to delete"*, is there anything that prevents you from clicking on the `delete` button? If more answers appear, it might become impossible, or at least more problematic. – Andrey Tyukin Oct 13 '18 at 14:22

2 Answers2

2

Some observations on your code:

  • You only look at the first (0th) element, and never increment i, so you don't check any of the subsequent elements for duplication.
  • The length argument is redundant, since we can discover the length of the Array, s, via its .length (or .size) attribute. Using the .length attribute is safer, because it is always valid. For example, duplicate(Array(1, 2, 3, 4, 5, 3), 10) causes an exception (java.lang.ArrayIndexOutOfBoundsException) since the array doesn't have 10 members.
  • You initialize j to have the same value as i, and then compare s(i) == s(j), so you're always going to get a duplicate on the first element, even if there's no duplication in the array.
  • You return result (which indicates whether you've found a result), rather than isDupli (which indicates whether you found a duplicate). Fortunately, we only need one of these, since finding a result is the same as finding a duplicate.

Here's another version that fixes these problems, and simplifies some code:

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

However, while this is perfectly OK procedural code, in Scala we can use a much better functional style. (Procedural code uses vars, while loops, etc. which is frowned upon in 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)
}

This might look rather complex, at first glance, but note that it doesn't have any var declarations or while loops. Of course, this a roll-your-own solution. There are far simpler methods of achieving this using other Array functions.

Mike Allen
  • 8,139
  • 2
  • 24
  • 46
-1

In your code the variable isDupli of no use because anyway you are returning result Boolean variable. Also, you are not incrementing variable i. You can use for loop as below:

 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
  }

In 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
RAGHHURAAMM
  • 1,099
  • 7
  • 15