连接类型具有 Show 实例的多个值

Posted

技术标签:

【中文标题】连接类型具有 Show 实例的多个值【英文标题】:Concatenating several values where the type has a Show instance 【发布时间】:2021-07-27 04:55:06 【问题描述】:

我想编写一个函数showAll,它接受一个List 的值并生成一个String,该String 是通过连接每个值的String 表示获得的,使用隐式范围内可用的Show 实例.

除了Show 实例的存在之外,列表元素的类型应该没有限制。

例如:

case class Person(name: String)
implicit val showPerson: Show[Person] = Show.by(_.name)
showAll(List(1, Person("Martin")))

应该输出:

1 Martin

在这种情况下,函数使用 Show[Int]Show[Person] 实例。

函数的正确签名是什么?

谢谢。

【问题讨论】:

问题是 List 的类型是 List[Any],没有 Show 没有简单的方法来拥有每个元素的 Show。有很多技巧可以得到你想要的,从 magnet 模式,到创建一个自定义类,用它的 show 实例压缩每个元素,再到使用 Shapeless 来做自动压缩。 确实,这就是问题所在。我的第一个想法是添加一些常见的超类型 T,然后为 T 编写一个显示实例,但我想知道是否可以通过某种方式增强签名来解决它。无形看起来很有趣。 检查this (search for the section called "Bonus Round: How do we deal with collections?") - 如果你设法让它工作,请发布答案! :) 你坚持List 还是可变参数也适合你?喜欢showAll(1, person) 【参考方案1】:

这是我的示例代码,它可能会解决您的问题。 我已经创建了通用方法 show all,因为您需要显示 List 的元素。也是特定字段值的隐式方法。 MyClass 轨迹是标识符。如果 Myclass 不会被任何案例扩展,则不会打印特定类别的字段。

trait Myclass
  case class Person(name: String) extends Myclass
  case class Admin(name: String,age:Long) extends Myclass

  def main(args: Array[String]): Unit = 
    showAll[Myclass](List(1, 2, Person("Martin"),Admin("Bob",30)))
  

  implicit def showField: String = "name"

  def showAll[T <: Myclass : ClassTag](listOfValues: List[Any]): Unit = 
    listOfValues.foreach  data =>
      if (data.isInstanceOf[T]) 
        val myInstance= data.asInstanceOf[T]
        val fld = myInstance.getClass.getDeclaredField(showField)
        fld.setAccessible(true)
        val value = fld.get(myInstance).asInstanceOf[String]
        print(value + " ")
      
      else
        print(data + " ")
    
  

【讨论】:

以上是关于连接类型具有 Show 实例的多个值的主要内容,如果未能解决你的问题,请参考以下文章

具有 Linq 和默认值的多个左连接

为啥在具有多个连接的 WHERE 子句中,子查询比文字值执行得更好?

具有多个带有 AND 类型逻辑连接的 where IN 子句的配置单元查询

具有多个左外连接的 SQL Server 查询挂起

具有匹配索引列的多个表的数据框连接值列

verilog 中顶层模块实例引用多个模块时端口怎么连接