Với Danh sách sau đây:Có cách nào an toàn trong Scala để chuyển đổi một Danh sách các danh sách dài bất bình đẳng không?
val l = List(List(1, 2, 3), List(4, 5), List(6, 7, 8))
Nếu tôi cố gắng transpose nó, Scala sẽ ném các lỗi sau:
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...
Điều này là do List.transpose
giả danh sách bằng độ dài và do đó sử dụng phương pháp head
:
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
}
Tôi muốn nhận các thông tin sau:
List(List(1, 4, 6), List(2, 5, 7), List(3, 8))
Đang viết phiên bản riêng của mình là transpose
cách tốt nhất để làm điều này? Đây là những gì tôi đã đưa ra:
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
}
Cập nhật: tôi đã quan tâm đến việc so sánh tốc độ của các giải pháp khác nhau được cung cấp ở đây, vì vậy tôi đặt lại với nhau ít điểm chuẩn sau:
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 })
}
}
My lệnh là:
scala PFTranspose 5 out.log
scala ACTranspose 5 out.log
scala ETranspose 5 out.log
kết quả của tôi là:
PRTranspose$ 10 0 1 1 0
ACTranspose$ 9 2 0 0 0
ETranspose$ 9 3 2 3 1
Bạn có ý định xử lý trường hợp danh sách đầu tiên (Danh sách (1,2,3)) của đầu vào không phải là kích thước tối đa của tất cả các danh sách. Ví dụ. làm thế nào để bạn xử lý đầu vào của Danh sách (Danh sách (1,2,3), Danh sách (4,5,99,100), Danh sách (6,7,8))? –
FWIW, Scala 2.8 không có lỗi này. –
Nhưng, nó có một lỗi nếu danh sách đầu tiên không phải là ít nhất là tuyệt vời như bất kỳ khác. –