[SCALA] 불평등 길이리스트의 목록을 전치하는 스칼라에서 안전한 방법이 있습니까?
SCALA불평등 길이리스트의 목록을 전치하는 스칼라에서 안전한 방법이 있습니까?
다음 목록을 감안할 때 :
val l = List(List(1, 2, 3), List(4, 5), List(6, 7, 8))
나는 그것을 전치하려고하면, 스칼라는 다음과 같은 오류가 발생합니다 :
scala> List.transpose(l)
java.util.NoSuchElementException: head of empty list
at scala.Nil$.head(List.scala:1365)
at scala.Nil$.head(List.scala:1362)
at scala.List$$anonfun$transpose$1.apply(List.scala:417)
at scala.List$$anonfun$transpose$1.apply(List.scala:417)
at scala.List.map(List.scala:812)
at scala.List$.transpose(List.scala:417)
at .<init>(<console>:6)
at .<clinit>(<console>)
at RequestResult...
List.transpose가 동일한 길이의 목록을 가정하고 있으므로 헤드 방식을 사용하기 때문입니다 :
def transpose[A](xss: List[List[A]]): List[List[A]] = {
val buf = new ListBuffer[List[A]]
var yss = xss
while (!yss.head.isEmpty) {
buf += (yss map (_.head))
yss = (yss map (_.tail))
}
buf.toList
}
나는 다음을 좀하고 싶습니다 :
List(List(1, 4, 6), List(2, 5, 7), List(3, 8))
전치 내 자신의 버전이 작업을 수행하는 가장 좋은 방법을 쓰고있다? 이것은 내가 생각 해낸 것입니다 :
def myTranspose[A](xss: List[List[A]]): List[List[A]] = {
val buf = new ListBuffer[List[A]]
var yss = xss
while (!yss.head.isEmpty) {
buf += (yss filter (!_.isEmpty) map (_.head))
yss = (yss filter (!_.isEmpty) map (_.tail))
}
buf.toList
}
업데이트 : 내가 함께 다음과 같은 작은 벤치 마크를 넣어, 그래서 내가 여기에 제공되는 다른 솔루션의 속도를 비교에 관심이되었다 :
import scala.testing.Benchmark
import scala.collection.mutable.ListBuffer
trait Transpose extends Benchmark {
def transpose[Int](xss: List[List[Int]]): List[List[Int]] = Nil
val list: List[List[Int]] = List(List(1,2,3), Nil, List(4,5,99,100), List(6,7,8))
def run = {
val l = transpose(list)
println(l)
l
}
}
object PRTranspose extends Transpose {
override def transpose[Int](xss: List[List[Int]]): List[List[Int]] = {
val buf = new ListBuffer[List[Int]]
var yss = xss
while (!yss.head.isEmpty) {
buf += (yss filter (!_.isEmpty) map (_.head))
yss = (yss filter (!_.isEmpty) map (_.tail))
}
buf.toList
}
}
object ACTranspose extends Transpose {
override def transpose[Int](xss: List[List[Int]]): List[List[Int]] = {
val b = new ListBuffer[List[Int]]
var y = xss filter (!_.isEmpty)
while (!y.isEmpty) {
b += y map (_.head)
y = y map (_.tail) filter (!_.isEmpty)
}
b.toList
}
}
object ETranspose extends Transpose {
override def transpose[Int](xss: List[List[Int]]): List[List[Int]] = xss.filter(!_.isEmpty) match {
case Nil => Nil
case ys: List[List[Int]] => ys.map{ _.head }::transpose(ys.map{ _.tail })
}
}
내 명령했다 :
scala PFTranspose 5 out.log
scala ACTranspose 5 out.log
scala ETranspose 5 out.log
내 결과는 :
PRTranspose$ 10 0 1 1 0
ACTranspose$ 9 2 0 0 0
ETranspose$ 9 3 2 3 1
해결법
-
==============================
1.이것은 어떤가요:
이것은 어떤가요:
scala> def transpose[A](xs: List[List[A]]): List[List[A]] = xs.filter(_.nonEmpty) match { | case Nil => Nil | case ys: List[List[A]] => ys.map{ _.head }::transpose(ys.map{ _.tail }) | } warning: there were unchecked warnings; re-run with -unchecked for details transpose: [A](xs: List[List[A]])List[List[A]] scala> val ls = List(List(1, 2, 3), List(4, 5), List(6, 7, 8)) ls: List[List[Int]] = List(List(1, 2, 3), List(4, 5), List(6, 7, 8)) scala> transpose(ls) res0: List[List[Int]] = List(List(1, 4, 6), List(2, 5, 7), List(3, 8)) scala> val xs = List(List(1,2,3), List(4,5,99,100), List(6,7,8)) xs: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 99, 100), List(6, 7, 8)) scala> transpose(xs) res1: List[List[Int]] = List(List(1, 4, 6), List(2, 5, 7), List(3, 99, 8), List(100))
-
==============================
2.나는 수학적으로 전치 작업 만 "직사각형 구조"에 잘 정의되어 있기 때문에 트랜스가리스트의 "사각형이 아닌"목록에 정의되지 않은 이유는 생각한다. 전치 동작의 바람직한 특성은 그 전치 (전치 (X)) == X. 이 목록의 사각형이 아닌 목록에있는 트랜스 작업의 당신의 일반화의 경우되지 않습니다.
나는 수학적으로 전치 작업 만 "직사각형 구조"에 잘 정의되어 있기 때문에 트랜스가리스트의 "사각형이 아닌"목록에 정의되지 않은 이유는 생각한다. 전치 동작의 바람직한 특성은 그 전치 (전치 (X)) == X. 이 목록의 사각형이 아닌 목록에있는 트랜스 작업의 당신의 일반화의 경우되지 않습니다.
또한, 스칼라에서 임의 컬렉션의-컬렉션 전치에 내 게시물을 살펴보고 사각형이 아닌 컬렉션 --컬렉션을 위해 그 일에 대해 생각합니다. 당신은 혼자가 구현을 떠나, 수학적으로 일치 정의로 끝날 것이다.
나는 이렇게 특이한 "트랜스"작업이 종종 유용하다는 동의하지만, 나는 또한 그들이 그들의 정확한 정의에 대한 잠재적 인 혼란의 표준 라이브러리에서 사용할 수 안된다고 생각합니다.
-
==============================
3.나는 알지 못한다 (그리고 상상할 수없는 -이 조금 이상한?! [의견 토론 참조]입니다하지 않습니다) 라이브러리 기능을하지만 코드 조금을 연마 할 수 있습니다 :
나는 알지 못한다 (그리고 상상할 수없는 -이 조금 이상한?! [의견 토론 참조]입니다하지 않습니다) 라이브러리 기능을하지만 코드 조금을 연마 할 수 있습니다 :
scala> def transpose(x: List[List[Int]]): List[List[Int]] = { | val b = new ListBuffer[List[Int]] | var y = x filter (!_.isEmpty) | while (!y.isEmpty) { | b += y map (_.head) | y = y map (_.tail) filter (!_.isEmpty) | } | b.toList | }
-
==============================
4.이것은 아마도 가장 깨끗한입니다 :
이것은 아마도 가장 깨끗한입니다 :
def transpose[T](l: List[List[T]]): List[List[T]] = l.flatMap(_.headOption) match { case Nil => Nil case head => head :: transpose(l.map(_.drop(1))) }
또는 더 효율적으로 수정 된 버전입니다 :
def transpose[T](l: List[List[T]]): List[List[T]] = l.flatMap(_.headOption) match { case Nil => Nil case head => head :: transpose(l.collect { case _ :: tail => tail }) }
-
==============================
5.어떻게 스칼라의 표준 API를 사용하여이 한 줄에 대해 :
어떻게 스칼라의 표준 API를 사용하여이 한 줄에 대해 :
((l map (_.toArray)) toArray).transpose map (_.toList) toList
이 일을 얻고 N 래퍼리스트의 길이이고 M은 래퍼 목록 내부의 긴리스트의 길이이고, O (N * M)입니다.
from https://stackoverflow.com/questions/1683312/is-there-a-safe-way-in-scala-to-transpose-a-list-of-unequal-length-lists by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 여러 매개 변수를 폐쇄 인수 유형을 추론하지 (0) | 2019.11.17 |
---|---|
[SCALA] 단일 스레드 구현보다는 Akka - 스트림 구현 속도가 느린 (0) | 2019.11.17 |
[SCALA] 이 경우 클래스 일치 패턴은 어떻게 작동합니까? (0) | 2019.11.17 |
[SCALA] 스파크 SQL 중첩 withColumn (0) | 2019.11.17 |
[SCALA] 스파크 스칼라 : 시간 또는 분에 의해 두 열의 참조 DateDiff (0) | 2019.11.17 |