我想实现一个具有以下特征的函数:
array
(Array[A]
)和一些pieces
作为参数返回(Int
)array
个pieces
数组中的array
数组。pieces
的长度不是split :: [a] -> Int -> [[a]]
split list pieces = go list (length list `div` pieces)
where
go xs n | l > n && m == 0 = take n xs : go (drop n xs) n
| l > n = take (n + 1) xs : go (drop (n + 1) xs) n
| otherwise = [xs]
where
l = length xs
m = l `mod` n
的倍数)Array
虽然在Scala中我遇到很多困难来编写这个(基本)函数。对于递归,if
似乎没有适应。然后,允许我实现我在haskell中使用的那种警卫的a
结构不允许代替表达式,这对我来说似乎很奇怪。我遇到的另一个问题是我不知道如何使我的scala代码具有多态性(就像我的Haskell代码一样)。最后但并非最不重要的是,我不知道如何制作Array
等效的多态,而且还有{{1}}实例,因为Scala中有许多基本集合。
我可以使用完整的解释解决方案或简单的提示来回答我的误解。
答案 0 :(得分:2)
翻译非常简单。我没有单独调用take
和drop
,而是使用可能更高效的splitAt
。当然,你可以使这个尾递归。而且我还认为“惯用”Scala可能在方法中使用IndexedSeq.newBuilder
,这可能再次更有效,但我想这不是你想要的。
请注意,Scala的数组是可变的,因此您需要Vector
或更通用的IndexedSeq
。
import collection.immutable.{IndexedSeq => ISeq}
def split[A](seq: ISeq[A], pieces: Int): ISeq[ISeq[A]] = {
val n = seq.size / pieces
def loop(xs: ISeq[A]): ISeq[ISeq[A]] = {
val l = xs.size
if(l > n) {
val m = l % n
val (begin, end) = xs.splitAt(if(m == 0) n else n + 1)
begin +: loop(end)
} else ISeq(xs)
}
loop(seq)
}
split(1 to 20, 3) // correct