我正在尝试通过转换为HList将一个案例类转换为另一个案例类。
df2 %>%
mutate(rn =row_number()) %>%
pivot_longer(cols = -rn, names_to = c(".value", "date"),
names_sep="(?<=[a-z])(?=[0-9])") %>%
arrange(rn, date) %>%
group_by(rn) %>%
summarise_at(vars(zip:child), ~ last(.[!is.na(.)])) %>%
ungroup %>%
select(-rn) %>%
rename_all( ~ str_c(., '_agg')) %>%
bind_cols(df2, .)
# zip20190601 zip20180401 zip20171001 zip20160801 income20190601 income20180401 income20171001 income20160801 child20160801 child20171001
#1 NA 11440 12016 15686 75038 63573 82391 47517 0 1
#2 13089 12626 13670 16155 89494 64984 62603 47252 0 1
#3 13258 12249 13333 16819 NA NA 48231 45729 0 1
#4 NA NA 18480 18611 89480 67348 55516 45863 0 1
#5 13990 10497 12573 13406 70053 63850 87833 48332 1 2
#6 17005 11491 15227 17518 78087 70741 46318 47823 1 2
#7 17174 17006 13461 11189 76780 66649 54578 46196 1 2
#8 12452 15317 18049 14284 76654 73583 70090 48281 0 1
#9 18449 14262 11013 17810 91422 79722 53948 45986 0 1
#10 11429 11731 13564 14603 84282 60190 45133 46956 0 1
# child20180401 child20190601 zip_agg income_agg child_agg
#1 1 2 11440 75038 2
#2 1 2 13089 89494 2
#3 1 2 13258 48231 2
#4 1 2 18480 89480 2
#5 2 3 13990 70053 3
#6 2 3 17005 78087 3
#7 2 3 17174 76780 3
#8 1 2 12452 76654 2
#9 1 2 18449 91422 2
#10 1 2 11429 84282 2
我可以通过gem.to从Source转换为HList,通过gen.from从HList转换为Destination。
我为Source上的每种参数类型编写了一个Converter,以将其转换为Destination中的相应类型,但是我不确定如何递归遍历HList。我的尝试显示在下面的case class Source(p1:S1, p2:S2) -> HList[S1:+:S2] -> HList[D1:+:D2] ->case class Destination(p1:D1,p2:D2)
hlistEncoder
我使用这种方法来测试HList到HList的转换
trait Converter[T] {
def convert(t:T): Datastructure
}
object Converter {
implicit object StrDatastructure extends Converter[String]{
def convert(t:String) = Datastructure.Str(t)
}
implicit object NumDatastructure extends Converter[Double]{
def convert(t :Double) = Datastructure.Num(t)
}
implicit object IncDatastructure extends Converter[Inc]{
def convert(t :Inc) = Datastructure.Incc(t)
}
implicit def SeqDatastructure[T: Converter]: Converter[Seq[T]] = new Converter[Seq[T]]{
def convert(t: Seq[T]) = {
Datastructure.Listt(t.map(implicitly[Converter[T]].convert):_*)
}
}
//HList traversals
implicit object hnilDatastructure extends Converter[HNil]{
def convert(t: HNil) = Datastructure.Hnill(t)
}
implicit def hlistEncoder[H, T <: HList](implicit
hEncoder: Converter[H],
tEncoder: Converter[T]
): Converter[H :: T] = new Converter[H :: T] {
def apply(h:H, t:T)= {
case (h :: t) => hEncoder.convert(h) ++ tEncoder.convert(t)
}
}
}
有什么想法如何实现def convertToDatastructureN[T](x: T)(implicit converter: Converter[T]): Datastructure = {
converter.convert(x)
}
case class Inc(i:Int)
case class Source(i: Int, n:Inc)
val x = Generic[Source]
val xHlist = x.to(Source(99, Inc(5)))
convertToDatastructureN(xHlist)
?
答案 0 :(得分:3)
我想你有
sealed trait Datastructure
object Datastructure {
case class Str(t: String) extends Datastructure
case class Num(t: Double) extends Datastructure
case class Incc(t: Inc) extends Datastructure
case class Listt(t: Datastructure*) extends Datastructure
case class Hnill(t: HNil) extends Datastructure
}
您希望您的类型类Converter
将T
转换为Datastructure
。而且(HList[S1:+:S2] -> HList[D1:+:D2]
,我想应该用::
代替:+:
),您还希望将HList
的子类型转换为HList
的子类型(而不是HList
本身,因为否则Generic
无法还原案例类)。所以要么修改您的类型类
trait Converter[T] {
type Out
def convert(t:T): Out
}
或者您需要两个类型类:原始的Converter
和
trait HListConverter[T <: HList] {
type Out <: HList
def convert(t:T): Out
}
此外,当前您的Converter
很粗糙。它将每个T
转换为Datastructure
而不是Datastructure
的特定子类型。这意味着Generic
将仅能还原形状的案例类
MyClass(x: Datastructure)
MyClass(x: Datastructure, y: Datastructure)
...
这真的是您想要的吗?如果是这样,那么还可以,如果不需要,则需要
MyClass(x: Str)
MyClass(x: Num, y: Incc)
...
然后又需要
trait Converter[T] {
type Out
def convert(t:T): Out
}
您可以使用标准的HListConverter
代替shapeless.ops.hlist.Mapper
。