All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tarao.collection.relation.Join.scala Maven / Gradle / Ivy

The newest version!
package com.github.tarao
package collection
package relation

import scala.language.{higherKinds, implicitConversions}

/** A class to describe a join of two sequences. */
case class Join[A, B, K, It[X] <: IterableLike[X, It, It[X]]](
  left: It[A],
  right: Iterable[B],
  leftKey: A => K,
  rightKey: B => K,
  default: K => Option[B]
) {
  private type R = (A, B)

  private def applyTo[It2[X] <: IterableLike[X, It2, It2[X]], R2](
    f: R => R2,
    s: It2[A]
  )(implicit
    bf: CanBuildFrom[It2[A], R2, It2[R2]]
  ): It2[R2] = {
    val m = {
      val m: Map[K, Option[B]] =
        right.view.map(x => rightKey(x) -> Some(x)).toMap
      m.withDefault(default)
    }
    s.flatMap(x => m(leftKey(x)).map(y => f((x, y))))
  }

  def into[R2](f: R => R2)(implicit
    bf: CanBuildFrom[It[A], R2, It[R2]]
  ): It[R2] = applyTo(f, left)

  def result(implicit bf: CanBuildFrom[It[A], R, It[R]]): It[R] =
    applyTo(identity, left)

  def toLazyList: LazyList[R] = applyTo(identity, left.convertTo(LazyList))
  def toStream: LazyList[R] = toLazyList
}
object Join {
  class Inner[A, B, It[X] <: IterableLike[X, It, It[X]]](
    left: It[A],
    right: Iterable[B]
  ) {
    def on[K](
      leftKey: A => K,
      rightKey: B => K
    ): Join[A, B, K, It] = Join(left, right, leftKey, rightKey, _ => None)
  }

  class Left[A, B, It[X] <: IterableLike[X, It, It[X]]](
    left: It[A],
    right: Iterable[B]
  ) {
    def on[K](
      leftKey: A => K,
      rightKey: B => K
    ): Left.On[A, B, K, It] = Left.On(left, right, leftKey, rightKey)
  }
  object Left {
    case class On[A, B, K, It[X] <: IterableLike[X, It, It[X]]](
      left: It[A],
      right: Iterable[B],
      leftKey: A => K,
      rightKey: B => K
    ) {
      private def toJoin(default: K => Option[B]): Join[A, B, K, It] =
        Join(left, right, leftKey, rightKey, default)

      def apply(default: B): Join[A, B, K, It] =
        toJoin(_ => Some(default))

      def apply(default: K => B): Join[A, B, K, It] =
        toJoin(x => Some(default(x)))
    }
  }

  implicit def toLazyList[A, B, K, It[X] <: IterableLike[X, It, It[X]]](
    join: Join[A, B, K, It]
  ): LazyList[(A, B)] = join.toLazyList
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy