कहो मेरे पास इस तरह की एक विधि है:

def getClassFromIterable(iterable: Iterable[Any]): Class[_] = {
  iterable.head.getClass
}

यह सूची के शीर्ष का वर्ग प्राप्त करेगा, लेकिन सूची खाली होने पर विफल हो जाएगा।
मैं एक उत्तीर्ण सूची की कक्षा कैसे प्राप्त कर सकता हूं जिसमें शून्य या अधिक तत्व हैं?

1
Jared DuPont 17 फरवरी 2020, 23:37
आपको पहली जगह इसकी आवश्यकता क्यों है? कोई भी का उपयोग करना एक कोड गंध है और किसी तत्व के class को प्राप्त करने के लिए प्रतिबिंब की आवश्यकता होती है (और इसके प्रकार के साथ भ्रमित करें) एक डिज़ाइन समस्या का संकेत है।
 – 
Luis Miguel Mejía Suárez
17 फरवरी 2020, 23:39
मैं एक इटेरेबल ऑफ केस क्लासेस (या कोई ऑब्जेक्ट) को इसके फ़ील्ड्स की 2डी स्ट्रिंग टेबल में बदलने के लिए एक फंक्शन बना रहा हूं, एक साधारण उदाहरण पॉइंट्स की सूची को एक्स और वाई के साथ कॉलम हेडर के रूप में 2 वाइड टेबल में बदल देगा।
 – 
Jared DuPont
17 फरवरी 2020, 23:41
1
आपको इस पद्धति की आवश्यकता नहीं है, बस एक मांगें आपकी मूल विधि पर ClasTagdef createTable[T](data: Iterable[T])(implicit ct: ClassTag[T]) जैसा कुछ आप इस पर runtimeclass पर कॉल कर सकते हैं।
 – 
Luis Miguel Mejía Suárez
18 फरवरी 2020, 00:34
ऐसा लगता है कि मेरा प्रश्न हल हो गया है, अगर आप इसे उत्तर के रूप में पोस्ट करते हैं तो मैं इसे स्वीकार करूंगा
 – 
Jared DuPont
18 फरवरी 2020, 00:49

2 जवाब

एक चिंतनशील समाधान के साथ लुइस के उत्तर का पूरक, विचार करें

import scala.reflect.runtime.universe._

def toTable[A <: Product](ps: List[A])(implicit ev: TypeTag[A]) = {
  val separator = "\t\t"
  ps match {
    case Nil =>
      val header = typeOf[A].members.collect { case m: MethodSymbol if m.isCaseAccessor => m.name }.toList
      header.mkString("", separator , "\n")

    case head :: _ =>
      val header = head.productElementNames.toList
      val rows = ps.map(_.productIterator.mkString(separator))
      header.mkString("", separator, "\n") + rows.mkString("\n")
  }
}

कौन सा आउटपुट

case class Point(x: Double, y: Double)
println(toTable(List(Point(1,2), Point(3,4))))

x       y
1.0     2.0
3.0     4.0

केस क्लास से फ़ील्ड नामों की सूची प्राप्त करें के आधार पर

2
Mario Galic 18 फरवरी 2020, 02:09

इस तरह की समस्याओं के लिए, कृपया टाइपक्लासका उपयोग करने पर विचार करें इसके बजाय

import scala.collection.immutable.ArraySeq

trait TableEncoder[T] {
  def header: ArraySeq[String]
  def asRow(t: T): ArraySeq[String]
}

object TableEncoder {
  def toTable[T](data: IterableOnce[T])
                (implicit encoder: TableEncoder[T]): ArraySeq[ArraySeq[String]] = {
    val builder = ArraySeq.newBuilder[ArraySeq[String]]

    builder.addOne(encoder.header)
    builder.addAll(data.iterator.map(encoder.asRow))

    builder.result()
  }
}

जिसे आप इस तरह इस्तेमाल कर सकते हैं:

final case class Point(x: Int, y: Int)
object Point {
  final implicit val PointTableEncoder: TableEncoder[Point] =
    new TableEncoder[Point] {
      override val header: ArraySeq[String] =
        ArraySeq("x", "y")

      override def asRow(point: Point): ArraySeq[String] =
        ArraySeq(
          point.x.toString,
          point.y.toString
        )
    }
}

TableEncoder.toTable(List(Point(1, 2), Point(3, 3))) 
// res: ArraySeq[ArraySeq[String]] = ArraySeq(
//   ArraySeq("x", "y"),
//   ArraySeq("1", "2"),
//   ArraySeq("3", "3")
// )
1
Mario Galic 18 फरवरी 2020, 02:10
विधि का बिंदु मेरे बिना हेडर को मैन्युअल रूप से निर्धारित करने या एक toRow फ़ंक्शन को परिभाषित करने के लिए एक तालिका उत्पन्न करना है। टेबल खाली होने के मामले को छोड़कर मेरे पास सब कुछ काम कर रहा है, इसलिए प्रश्न
 – 
Jared DuPont
18 फरवरी 2020, 00:17
आप टाइपक्लास प्राप्त करने की प्रक्रिया को आसान बनाने के लिए आकारहीन या मैगनोलिया पर एक नज़र डालना चाह सकते हैं, लेकिन मेरा विश्वास करें, इस प्रकार का बॉयलरप्लेट इसके लायक है। यह सुरक्षित है क्योंकि यह केवल तभी संकलित होगा जब मान को तालिका में बदला जा सकता है। यह तेज़ है क्योंकि यह प्रतिबिंब का उपयोग नहीं करता है। यह इस अर्थ में भी अधिक लचीला और सुरक्षित है कि आप परिभाषित करते हैं कि आप क्या उजागर करना चाहते हैं और किस क्रम में।
 – 
Luis Miguel Mejía Suárez
18 फरवरी 2020, 00:21