Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 更好的方法(功能性/不可变,但性能更好)编码一种算法,该算法在编码过程中从集合中删除项_Algorithm_Scala_Functional Programming_Immutability - Fatal编程技术网

Algorithm 更好的方法(功能性/不可变,但性能更好)编码一种算法,该算法在编码过程中从集合中删除项

Algorithm 更好的方法(功能性/不可变,但性能更好)编码一种算法,该算法在编码过程中从集合中删除项,algorithm,scala,functional-programming,immutability,Algorithm,Scala,Functional Programming,Immutability,我是Scala和函数式编程的初学者,我有一些算法代码可能有一些味道,因为它使用了可变性,但也有一个bug,部分原因是它是可变性的。我有两组二维点。集合1中的每个点都要与集合2中最近的点相关联(给定集合1相对于集合2的比例和偏移)。我们需要1对1的相关性,而不是1对多的相关性。我认为这意味着,当我们在集合2中找到与集合1中的点最近的点时,我们应该从集合2中删除前者,因为我们不希望再次匹配它。然而,也许有一种不变的/功能性的方式 下面的代码有一个错误,如果所有的点都从set2NotYetMatche

我是Scala和函数式编程的初学者,我有一些算法代码可能有一些味道,因为它使用了可变性,但也有一个bug,部分原因是它是可变性的。我有两组二维点。集合1中的每个点都要与集合2中最近的点相关联(给定集合1相对于集合2的比例和偏移)。我们需要1对1的相关性,而不是1对多的相关性。我认为这意味着,当我们在集合2中找到与集合1中的点最近的点时,我们应该从集合2中删除前者,因为我们不希望再次匹配它。然而,也许有一种不变的/功能性的方式

下面的代码有一个错误,如果所有的点都从set2NotYetMatched中删除,那么我们调用empty.minBy;这可以通过修改代码使其功能更少来解决,可能是使用for或while构造。但在我这么做之前,有没有更好的编码方法?以下是当前代码:

  protected def calcDistanceCostBetweenSets(
        set1: Seq[Point], set1StartX: Double, set1XScale: Double, set2Window: PointWindow, xImportance: Double
        ): CloudMatch = {

    require (!set1.isEmpty)

    var set2NotYetMatched = scala.collection.mutable.Set.empty ++= set2Window.subsetWithMargins

    val correlations = set1 map(set1Point => {
      val minDistPointAndDist = set2NotYetMatched.map(set2Point =>
        (
          set2Point,
          DistanceCostCalculator.calcPointToPointDistanceSquared(
            set1Point, set2Point, set1StartX, set2Window.marginStartX, set1XScale, xImportance)))
        .minBy(_._2)

      set2NotYetMatched -= ( minDistPointAndDist._1)
      new PointCorrelation(set1Point, Collections.singletonList(minDistPointAndDist._1), minDistPointAndDist._2)
    })
    val distanceCost = correlations.map(_.getCost).foldLeft(0.0)(_ + _)
    return new CloudMatch(
      set2Window.firstPointAlongX,
      set2Window.startIndexInOriginalSubset,
      distanceCost,
      Lists.newArrayList(JavaConversions.asJavaIterable(correlations)))
  }

虽然我对更好的答案很感兴趣,但我提出了一个更好的解决方案,使用递归算法(无可变性),使用尾部递归,每次递归时删除一项:

  protected def calcDistanceCostBetweenSets(set1: Seq[Point], set1StartX: Double, set1XScale: Double, set2Window: PointWindow, xImportance: Double): CloudMatch = {
    require (!set1.isEmpty)

    val correlations = findCorrelations(set1.toSet, set1StartX, set1XScale, set2Window.subsetWithMargins.toSet, set2Window.startX, xImportance)
    val distanceCost = correlations.map(_.getCost).foldLeft(0.0)(_ + _)
    new CloudMatch(
      set2Window.firstPoint,
      set2Window.startIndexInOriginalSubset,
      distanceCost,
      Lists.newArrayList(JavaConversions.asJavaIterable(correlations sortBy(_.getActualEvent.getStartX))))
  }

  private def findCorrelations(set1: Set[Point], set1StartX: Double, set1XScale: Double, set2Points: Set[Point], set2StartX: Double, xImportance: Double
                              ): List[EventCorrelation] = {
    findCorrelations(Nil, set1, set1 head, set2Points,
      DistanceCostCalculator.calcPointToPointDistanceSquared(_, _,
        set1StartX, set2StartX, set1XScale, xImportance))
  }

  private def findCorrelations(
                                correlations: List[EventCorrelation],
                                set1: Set[Point],
                                set1PointToFind: Point,
                                set2: Set[Point],
                                calculateCost : (Point, Point) => Double
                              ): List[EventCorrelation] = {

    val minDistPoint = set2.map(scorePoint =>
      (scorePoint, calculateCost(set1PointToFind, scorePoint))
    ).minBy(_._2)

    val correlation = new EventCorrelation(set1PointToFind, Collections.singletonList(minDistPoint._1), minDistPoint._2)
    val remainingSet1 = set1 - set1PointToFind;
    val remainingSet2 = set2 - minDistPoint._1

    if(remainingSet1.isEmpty || remainingSet2.isEmpty) correlations
    else findCorrelations(
      correlation :: correlations,
      remainingSet1,
      remainingSet1 head,
      remainingSet2,
      calculateCost);
  }

我认为一个好的方法是使用
foldLeft
跟踪当前的相关性和set2中保留的元素

有关
findCorrelations
方法,请参见下文。它类似于递归解决方案。一个显著的区别是您不必维护
remainingSet
。你觉得怎么样

private def findCorrelations(
  set1: Set[Point], 
  set1StartX: Double, 
  set1XScale: Double, 
  set2Points: Set[Point], 
  set2StartX: Double, 
  xImportance: Double
): List[EventCorrelation] = {

  def calculateCost(p1: Point, p2: Point): Double = {
    DistanceCostCalculator.calcPointToPointDistanceSquared(
      p1, p2,
      set1StartX, set2StartX, set1XScale, xImportance)
  }

  set1.foldLeft((List.empty[EventCorrelation], set2Points)) { 
    case ((correlationsAcc, set2PointsRemaining), set1PointToFind) =>
      if (set2PointsRemaining.isEmpty) {
        correlationsAcc
      } else {
        val (set2MinPoint, minDist) = set2PointsRemaining.map(scorePoint =>
          (scorePoint, calculateCost(set1PointToFind, scorePoint))
        ).minBy(_._2)

        val correlation = new EventCorrelation(
          set1PointToFind, 
          Collections.singletonList(set2MinPoint),
          minDist)

        (correlationsAcc + correlation, set2PointsRemaining - set2MinPoint)
      }
  }

有趣而优雅!非常感谢。