код для поиска дубликатов в массиве, Scala - PullRequest
0 голосов
/ 13 октября 2018

Я пытаюсь построить алгоритм, который может найти дубликаты в массиве, без использования каких-либо предварительно реализованных функций, таких как «сортировка» и т. Д.

У меня нет ошибки, но моя функция не работает…У тебя есть идеи почему?(Я только начинаю программирование на 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 голосов
/ 13 октября 2018

Некоторые замечания по вашему коду:

  • Вы смотрите только на первый (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

Однако, хотя это совершенно нормально процедурный код, в Scala мы можем использовать гораздо лучший функциональный стиль.(В процедурном коде используются 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 циклов.Конечно, это решение roll-your-own .Существуют гораздо более простые методы достижения этого с использованием других Array функций.

0 голосов
/ 13 октября 2018

В вашем коде переменная 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
...