Scala替换Arrays.binarySearch?

问题描述 投票:26回答:6

Scala for Java qazxsw poi有替代品吗?

问题是Scala的Arrays不是协变的,所以我必须首先投射我的int Arrays.binarySearch(Object[] array, object)

stringArray: Array[String]

有更好的解决方案吗?

java search scala programming-languages
6个回答
17
投票

据我所知,没有内置任何东西,但你可以使用stringArray.asInstanceOf[Array[Object]] 来轻松完成。像这样:

pimp-my-library pattern

如果您也需要,可以将其他class ObjectArrayTools[T <: AnyRef](a: Array[T]) { def binarySearch(key: T) = { java.util.Arrays.binarySearch(a.asInstanceOf[Array[AnyRef]],key) } } implicit def anyrefarray_tools[T <: AnyRef](a: Array[T]) = new ObjectArrayTools(a) scala> Array("a","fish","is","some","thing").binarySearch("some") res26: Int = 3 scala> Array("a","fish","is","some","thing").binarySearch("bye") res28: Int = -2 对象方法添加到同一个类中。

一般来说,我觉得习惯于总是导入你最喜欢的Scala实用程序的集合是个好主意。添加这样的功能非常容易,你可以这样做,而不是继续输入java.util.Arrays,只需稍加努力就可以让自己显着提高工作效率。


42
投票

Scala 2.11将.asInstanceOf[Array[AnyRef]]添加到标准库中。它使用二进制搜索索引序列,否则使用线性搜索。

scala.collection.Searching

4
投票

数组是有趣的野兽。如果您尝试使用'ObjectArrayTools'提供的示例中的代码:

import scala.collection.Searching._
Array(1, 2, 3, 4, 5).search(3)

你得到

Array(1, 2, 3, 4, 5).binarySearch(3)

有关Scala中Arrays的内容,请参阅error: value binarySearch is not a member of Array[Int] Array(1, 2, 3, 4, 5).binarySearch(3) 。在任何情况下,您都可以使用此代码,尽管它使用Seq而不是Array。但是,它还有使用Ordering的额外好处(它恰好也是一个Java Comparator。所以你可以根据需要自定义有序行为。)

this document

一些例子:

import _root_.scala.collection.JavaConversions._
import java.util.{Collections, List => JList}
class SearchableSeq[T](a: Seq[T])(implicit ordering: Ordering[T]) {
    val list: JList[T] = a.toList
    def binarySearch(key: T): Int = Collections.binarySearch(list, key, ordering)
}
implicit def seqToSearchable[T](a: Seq[T])(implicit ordering: Ordering[T]) = 
        new SearchableSeq(a)(ordering)

0
投票

在scala中编写它并不难

scala> List(1, 2, 3, 4, 5).binarySearch(3)
res0: Int = 2

scala> List(1D, 2D, 3D, 4D, 5D).binarySearch(3.5)
res1: Int = -4

scala> List("a","fish","is","some","thing").binarySearch("bye")
res2: Int = -2

0
投票

在提出这个问题已经有好几年了,想过做一些比较测试,希望它可以帮助一些人做出决定:

  object BSearch {
    def interative[T](array: Array[T], value: T)(implicit arithmetic: Numeric[T]): Int = {
      var left: Int = 0;
      var right: Int = array.length - 1;
      while (right > left) {
        val mid = left + (right - left) / 2
        val comp = arithmetic.compare(array(mid), value)
        if (comp == 0)
          return mid; //negative if test < value
        else if (comp > 0) //list(mid) > value
          right = mid - 1;
        else if (comp < 0) //list(mid) < value
          left = mid + 1;
      }
      -1;
    }


BSearch.interative(array, value)

3次运行后返回的结果(因为Scala编译器确实需要一些提升)

import scala.collection.Searching._
import _root_.scala.collection.JavaConversions._
import java.util.{Collections, List => JList}
import scala.reflect.ClassTag

class ObjectArrayTools[T <: Int](a: Array[T]) {
   def binarySearch(key: T) = {
     java.util.Arrays.binarySearch(a.asInstanceOf[Array[Int]],key)
   }
}

class SearchableSeq[T](a: Seq[T])(implicit ordering: Ordering[T]) {
    val list: JList[T] = a.toList
    def binarySearch2(key: T): Int = Collections.binarySearch(list, key, ordering)
}

object BinarySearch {
  implicit def anyrefarray_tools[T <: Int](a: Array[T]) = new ObjectArrayTools(a)
  implicit def seqToSearchable[T](a: Seq[T])(implicit ordering: Ordering[T]) =
          new SearchableSeq(a)(ordering)

  def main(args:Array[String]) {
    val informationArray = Array(1,2,3,4,5,6,7,8,9,10,11,12,14,15,18,20,22,23,25,26)
    val informationList = List(1,2,3,4,5,6,7,8,9,10,11,12,14,15,18,20,22,23,25,26)
    //val sortedArray = sortList(informationArray)
    val sortedArray = informationArray
    val sortedList = informationList

    for(x <- 0 to 2) {
      val startTime = System.nanoTime
      val result = binarySearch(sortedArray, 5)
      val result2 = binarySearch(sortedArray, 19)
      println(s"Custom search time elapsed: ${(System.nanoTime - startTime)}")

      val startTime2 = System.nanoTime
      val result3 = sortedArray.search(5)
      val result4 = sortedArray.search(19)
      println(s"Scala search time elapsed: ${(System.nanoTime - startTime2)}")

      val startTime3 = System.nanoTime
      val result5 = sortedArray.binarySearch(5)
      val result6 = sortedArray.binarySearch(19)
      println(s"Java search casting time elapsed: ${(System.nanoTime - startTime3)}")

      val startTime4 = System.nanoTime
      val result7 = sortedList.binarySearch2(5)
      val result8 = sortedList.binarySearch2(19)
      println(s"Java search as list time elapsed: ${(System.nanoTime - startTime4)}")


      val startTime9 = System.nanoTime
      val result10 = binarySearchWithImplicitConversion(sortedArray, 5)
      val result11 = binarySearchWithImplicitConversion(sortedArray, 19)
      println(s"Custom generic time elapsed: ${(System.nanoTime - startTime9)}")

      println("---")
    }
  }

  /*def sortList(list:Array[Int]):Array[Int] = {
    import com.walcron.etc.Quicksort._
    quickSort(list)
  }*/

  //def binarySearch[T <% Ordered[T]](list:Array[T], valueToBeSearch:T)(implicit t:ClassTag[T]):Int =  {
  def binarySearch(list:Array[Int], valueToBeSearch:Int):Int =  {
    def search(start:Int, end:Int):Int = {
      val pos = ((end - start) / 2) + start
      val curr = list(pos)

      if(curr == valueToBeSearch) {
        pos
      }
      else if((end - start) <= 1) {
        -1 * (pos + 1) // Indicates the value should be inserted
      }
      else if(valueToBeSearch > curr) {
        search(pos, end)
      }
      else {
        search(start, pos)
      }
    }

    search(0, list.length)
  }

  def binarySearchWithImplicitConversion[T <% Ordered[T]](list:Array[T], valueToBeSearch:T)(implicit t:ClassTag[T]):Int =  {
    def search(start:Int, end:Int):Int = {
      val pos = ((end - start) / 2) + start
      val curr = list(pos)

      if(curr == valueToBeSearch) {
        pos
      }
      else if((end - start) <= 1) {
        -1 * (pos + 1) // Indicates the value should be inserted
      }
      else if(valueToBeSearch > curr) {
        search(pos, end)
      }
      else {
        search(start, pos)
      }
    }

    search(0, list.length)
  }
}

一般来说,java二进制搜索执行方式更好;斯卡拉的搜索确实非常糟糕。还有另一个值得注意的表现,似乎泛型类型隐含地拖累了这里的性能(所以也许有人可以帮助修复泛型类型)......但是它间接表现出很大的性能影响。


-2
投票

@摩西 - 比里

如果您要在Scala中编写它,为什么要在Scala中用Java编写它?为什么不在Scala中实际写它?

Custom search time elapsed: 873373
Scala search time elapsed: 9322723
Java search casting time elapsed: 126380
Java search as list time elapsed: 7375826
Custom generic time elapsed: 4421972
---
Custom search time elapsed: 10372
Scala search time elapsed: 34885
Java search casting time elapsed: 10861
Java search as list time elapsed: 104596
Custom generic time elapsed: 57964
---
Custom search time elapsed: 9121
Scala search time elapsed: 31667
Java search casting time elapsed: 11815
Java search as list time elapsed: 53387
Custom generic time elapsed: 60773
© www.soinside.com 2019 - 2024. All rights reserved.