当某些元素不是数组时,在 Scala 2.8 中展平数组

发布于 2024-10-10 21:04:09 字数 360 浏览 1 评论 0原文

如果我有

var a = Array(Array(1, 2), 3, Array(4,5,6))

并且我想将其转换为

Array(1, 2, 3, 4, 5, 6)

最简单的方法是什么?

我也尝试过

def flatArray(a:Array[Any])= a.map(x => x match { case ar:Array[_] => ar; case _ => Array(x) } )

,但输出是 ArraySeq 类型,我无法看到如何将其转换为 Array

If I have

var a = Array(Array(1, 2), 3, Array(4,5,6))

and I want to convert this to

Array(1, 2, 3, 4, 5, 6)

what is the easiest way to do it? There is a solution for lists given in this post
but it does not work for arrays.

I also tried

def flatArray(a:Array[Any])= a.map(x => x match { case ar:Array[_] => ar; case _ => Array(x) } )

but the output is of type ArraySeq and I am not able to see how to convert it to Array

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扭转时空 2024-10-17 21:04:09
def flatArray[T : ClassManifest](a:Array[Any]) = 
  a.flatMap{
    case ar:Array[T] => ar
    case x: T => Array(x) 
  }

我也尝试过使用 #flatten 方法,但它在 NPE 上失败。

更新:回答 Jus12 的问题:

def flatArray[T : Manifest](a:Array[Any]) = 
  a.flatMap{
    case ar: Array[_] if ar.getClass.getComponentType == manifest[T].erasure => ar.asInstanceOf[Array[T]];
    case x => Array(x.asInstanceOf[T])
  }

当然整个解决方案不是类型安全的。原因是为了适应编译器的类型推断,将 Array(Array(1, 2), 3, Array(4,5,6)) 推断为 Array[Any] 。准确的类型是“IntArray[Int] 的数组”,但这是不可能的。就是创建一个 Either 元素数组,其中每个元素都是 Either[Int, Array[Int]] 并使用它:

object EitherView {
  type ||[A, B] = Either[A, B]
  // convenience of definition functions
  private def l[A,B](a: A): ||[A,B] = Left(a)
  private def r[A,B](b: B): ||[A,B] = Right(b)

  // implicit defs - stuttering-or
  implicit def aToOr2[A,B](a: A): A || B = l(a)
  implicit def bToOr2[A,B](b: B): A || B = r(b)
  implicit def aToOr3[A,B,C](a: A): A || B || C =  l(l(a))
  implicit def bToOr3[A,B,C](b: B): A || B || C = l(r(b))
  implicit def aToOr4[A,B,C,D](a: A): A || B || C || D = l(l(l(a)))
  implicit def bToOr4[A,B,C,D](b: B): A || B || C || D =  l(l(r(b)))
  implicit def aToOr5[A,B,C,D,E](a: A): A || B || C || D || E = l(l(l(l(a))))
  implicit def bToOr5[A,B,C,D,E](b: B): A || B || C || D || E = l(l(l(r(b))))
  // more? ...

}

import EitherView._

type CompoundArray[T] = Array[T || Array[T]]

object CompoundArray {
  def apply[T](elems: (T || Array[T])*) = elems.toArray
}

def flatArray[T : Manifest](a:CompoundArray[T]) = {
  a.flatMap{
    case Left(x) => Array(x)
    case Right(x) => x
  }
}

请参阅:

scala> val a = CompoundArray[Int](Array(1, 2), 3, Array(4,5,6))
a: Array[EitherView.||[Int,Array[Int]]] = Array(Right([I@1364b53), Left(3), Right([I@18b62e0))

scala> flatArray(a)
res0: Array[Int] = Array(1, 2, 3, 4, 5, 6)

scala> flatArray(CompoundArray[String](Array("hi"), "bye"))
res4: Array[String] = Array(hi, bye)

scala> flatArray(CompoundArray[String](Array("hi"), 3))
<console>:13: error: type mismatch;
 found   : Int(3)
 required: EitherView.||[String,Array[String]]
       flatArray(CompoundArray[String](Array("hi"), 3))
                                                    ^

注意:EitherView 的原始想法是由@Mitch Blevins 提出的: http://cleverlytitled.blogspot.com/2009/03/disjoint -bounded-views-redux.html

def flatArray[T : ClassManifest](a:Array[Any]) = 
  a.flatMap{
    case ar:Array[T] => ar
    case x: T => Array(x) 
  }

I've tried also to use the #flatten method, but it fails on NPE.

Update: To answer Jus12's question:

def flatArray[T : Manifest](a:Array[Any]) = 
  a.flatMap{
    case ar: Array[_] if ar.getClass.getComponentType == manifest[T].erasure => ar.asInstanceOf[Array[T]];
    case x => Array(x.asInstanceOf[T])
  }

Of course the whole solution is not type safe. The reason is to accommodate the compiler's type inference which infers Array(Array(1, 2), 3, Array(4,5,6)) as Array[Any]. An accurate type is "an array of either Int or Array[Int]", but that is not possible. What is is to create an array of Either elements where each element is Either[Int, Array[Int]] and work with that:

object EitherView {
  type ||[A, B] = Either[A, B]
  // convenience of definition functions
  private def l[A,B](a: A): ||[A,B] = Left(a)
  private def r[A,B](b: B): ||[A,B] = Right(b)

  // implicit defs - stuttering-or
  implicit def aToOr2[A,B](a: A): A || B = l(a)
  implicit def bToOr2[A,B](b: B): A || B = r(b)
  implicit def aToOr3[A,B,C](a: A): A || B || C =  l(l(a))
  implicit def bToOr3[A,B,C](b: B): A || B || C = l(r(b))
  implicit def aToOr4[A,B,C,D](a: A): A || B || C || D = l(l(l(a)))
  implicit def bToOr4[A,B,C,D](b: B): A || B || C || D =  l(l(r(b)))
  implicit def aToOr5[A,B,C,D,E](a: A): A || B || C || D || E = l(l(l(l(a))))
  implicit def bToOr5[A,B,C,D,E](b: B): A || B || C || D || E = l(l(l(r(b))))
  // more? ...

}

import EitherView._

type CompoundArray[T] = Array[T || Array[T]]

object CompoundArray {
  def apply[T](elems: (T || Array[T])*) = elems.toArray
}

def flatArray[T : Manifest](a:CompoundArray[T]) = {
  a.flatMap{
    case Left(x) => Array(x)
    case Right(x) => x
  }
}

See:

scala> val a = CompoundArray[Int](Array(1, 2), 3, Array(4,5,6))
a: Array[EitherView.||[Int,Array[Int]]] = Array(Right([I@1364b53), Left(3), Right([I@18b62e0))

scala> flatArray(a)
res0: Array[Int] = Array(1, 2, 3, 4, 5, 6)

scala> flatArray(CompoundArray[String](Array("hi"), "bye"))
res4: Array[String] = Array(hi, bye)

scala> flatArray(CompoundArray[String](Array("hi"), 3))
<console>:13: error: type mismatch;
 found   : Int(3)
 required: EitherView.||[String,Array[String]]
       flatArray(CompoundArray[String](Array("hi"), 3))
                                                    ^

Note: The original idea for EitherView is by @Mitch Blevins: http://cleverlytitled.blogspot.com/2009/03/disjoint-bounded-views-redux.html

爱的那么颓废 2024-10-17 21:04:09

与 IttayD 类似,没有 ClassManifest,并具有 Array[Any] 作为结果。

    scala> a.flatMap{
     |          case ar: Array[_] => ar
     |          case x => List(x)
     | }
    res4: Array[Any] = Array(1, 2, 3, 4, 5, 6)

Similar to IttayD, without ClassManifest, and has Array[Any] as result.

    scala> a.flatMap{
     |          case ar: Array[_] => ar
     |          case x => List(x)
     | }
    res4: Array[Any] = Array(1, 2, 3, 4, 5, 6)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文