2017-08-24 4 views
4

Kann jemand zwei Datensätze ausrichten, wenn sie denselben Namen haben wie Felder, aber nicht die gleichen Werte, die in Spalte eingeschlossen sind, eine andere Option, die ich ausrichten muss die Reihenfolge ist andersFormlose Ausrichtung mit verschiedenen Typen, aber gleichen Beschriftungen

import shapeless._ 
import shapeless.labelled.{FieldType, field} 
import shapeless.ops.hlist.{Align, ToTraversable, ZipWith} 

object ShapelessTest { 


    def zipClasses[A, B, P <: Poly2, ARepr <: HList, BRepr <: HList, R <: HList, X] 
    (a: A, b: B, f: P)(
    implicit 
    aGen : LabelledGeneric.Aux[A, ARepr], 
    bGen : LabelledGeneric.Aux[B, BRepr], 
// align : Align[ARepr, BRepr], 
    zipWith : ZipWith.Aux[ARepr, BRepr, P, R], 
    toTrav: ToTraversable.Aux[R, List, X] 
): List[X] = 
    aGen.to(a).zipWith(bGen.to(b))(f).toList 
// align.apply(aGen.to(a)).zipWith(bGen.to(b))(f).toList 



    def main(args: Array[String]): Unit = { 


    case class Column[A](value: A) 

    case class DTable(id: Column[Long], s2: Column[Int], s: Column[String]) 
    case class DFilter(id: Option[Long], s: Option[String], s2: Option[Int]) 

    object filter extends Poly2 { 
     implicit def repr[K <: Symbol, V] = at[FieldType[K, Column[V]], FieldType[K, Option[V]]] { (a, b) => 
     field[K]((a, b).asInstanceOf[(Any, Any)]) 
     } 
    } 

    val dTable = new DTable(Column(1L), Column(3), Column("s")) 
    val dFilter = new DFilter(Option(222L), Option("second"), Option(234)) 


// def filter[A](col: Column[A], filterCriteria: Option[A]): Option[Boolean] = ??? 

// def filterClass(table: DTable, filter: DFilter): List[Option[Boolean]] = ??? 
    def filterClass(t: DTable, f: DFilter): List[(Any, Any)] = zipClasses(t, f, filter) 

    val res = filterClass(dTable, dFilter) 
    println(res) 

    } 

} 

ich zwei Datensätze mit genau dem gleichen Typ ausrichten kann, und ich kann mit zwei Aufzeichnungen sogar zipWith tun, wenn der Typ nicht einen exakt ist, aber sie müssen durch Tasten ausgerichtet werden.

Danke

Antwort

2

Wenn wir Ähnlichkeiten in Feldnamen ignorieren und konzentrieren sich auf Typen können wir folgendes tun:

def alignRecordByTypeInsideConstructor[A, B, L1 <: HList, L2 <: HList, 
     F[_], G[_], L3 <: HList, L4 <: HList, Out <: HList](a: A, b: B, f: F ~> Id, g: Id ~> G)(
     implicit 
     gen1: Generic.Aux[A, L1], 
     gen2: Generic.Aux[B, L2], 
     comapped1: Comapped.Aux[L1, F, L3], 
     natTRel1: NatTRel[L1, F, L3, Id], 
     comapped2: Comapped.Aux[L2, G, L4], 
     natTRel2: NatTRel[L2, G, L4, Id], 
     align: Align[L3, L4], 
     mapped: Mapped.Aux[L4, G, Out], 
     natTRel3: NatTRel[L4, Id, Out, G] 
    ): Out = 
     alignByTypeInsideConstructor[L1, L2, F, G, L3, L4, Out](gen1.to(a), gen2.to(b), f, g) 

    def alignByTypeInsideConstructor[L1 <: HList, L2 <: HList, 
     F[_], G[_], L3 <: HList, L4 <: HList, Out <: HList](l1: L1, l2: L2, f: F ~> Id, g: Id ~> G)(
     implicit 
     comapped1: Comapped.Aux[L1, F, L3], 
     natTRel1: NatTRel[L1, F, L3, Id], 
     comapped2: Comapped.Aux[L2, G, L4], 
     natTRel2: NatTRel[L2, G, L4, Id], 
     align: Align[L3, L4], 
     mapped: Mapped.Aux[L4, G, Out], 
     natTRel3: NatTRel[L4, Id, Out, G]): Out = 
     natTRel3.map(g, align(natTRel1.map(f, l1))) 

    object columnToId extends (Column ~> Id) { 
     override def apply[A](column: Column[A]): A = column match { 
     case Column(a) => a 
     } 
    } 

    object idToOption extends (Id ~> Option) { 
     override def apply[A](a: A): Option[A] = Some(a) 
    } 

    alignByTypeInsideConstructor(
     Column(1L) :: Column(2) :: Column("a") :: HNil, 
     Option(3L) :: Option("b") :: Option(4) :: HNil, 
     columnToId, 
     idToOption 
    ) 

    //Some(1) :: Some(a) :: Some(2) :: HNil 

    alignRecordByTypeInsideConstructor(
     DTable(Column(1L), Column(2), Column("a")), 
     DFilter(Option(3L), Option("b"), Option(4)), 
     columnToId, 
     idToOption 
    ) 

    //Some(1) :: Some(a) :: Some(2) :: HNil 
+1

Sie Dmytro danken – user1698641

Verwandte Themen