Bir öğe listesini en fazla N öğeli listelere nasıl bölebilirim?
örn: 7 öğeli bir liste verildiğinde, son grubu muhtemelen daha az öğeyle bırakarak 4'lü gruplar oluşturun.
split(List(1,2,3,4,5,6,"seven"),4)
=> List(List(1,2,3,4), List(5,6,"seven"))
Bir öğe listesini en fazla N öğeli listelere nasıl bölebilirim?
örn: 7 öğeli bir liste verildiğinde, son grubu muhtemelen daha az öğeyle bırakarak 4'lü gruplar oluşturun.
split(List(1,2,3,4,5,6,"seven"),4)
=> List(List(1,2,3,4), List(5,6,"seven"))
Yanıtlar:
Sanırım arıyorsun grouped. Bir yineleyici döndürür, ancak sonucu bir listeye dönüştürebilirsiniz,
scala> List(1,2,3,4,5,6,"seven").grouped(4).toList
res0: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
Kaydırma yöntemini kullanarak görevi yapmanın çok daha kolay yolu var. Şu şekilde çalışır:
val numbers = List(1, 2, 3, 4, 5, 6 ,7)
Listeyi 3 boyutlu daha küçük listelere bölmek istediğinizi varsayalım.
numbers.sliding(3, 3).toList
sana vereceğim
List(List(1, 2, 3), List(4, 5, 6), List(7))
Veya kendiniz yapmak istiyorsanız:
def split[A](xs: List[A], n: Int): List[List[A]] = {
if (xs.size <= n) xs :: Nil
else (xs take n) :: split(xs drop n, n)
}
kullanın:
scala> split(List(1,2,3,4,5,6,"seven"), 4)
res15: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
edit : bunu 2 yıl sonra gözden geçirdikten sonra, bu uygulamayı önermem çünkü sizeO (n) ve bu nedenle bu yöntem O (n ^ 2) 'dir, bu da yerleşik yöntemin neden büyük listeler için daha hızlı hale geldiğini açıklar. aşağıdaki yorumlarda belirtildiği gibi. Aşağıdaki gibi verimli bir şekilde uygulayabilirsiniz:
def split[A](xs: List[A], n: Int): List[List[A]] =
if (xs.isEmpty) Nil
else (xs take n) :: split(xs drop n, n)
hatta (biraz) daha verimli kullanarak splitAt:
def split[A](xs: List[A], n: Int): List[List[A]] =
if (xs.isEmpty) Nil
else {
val (ys, zs) = xs.splitAt(n)
ys :: split(zs, n)
}
xs splitAt nkombinasyona bir alternatiftir xs take nvexs drop n
splitAtyerine kullanıyor take/ dropperformansı ortalama% 4 civarında artırıyor gibi görünüyor ; her ikisi de% 700-1000 daha hızlı .grouped(n).toList!
grouped-toListbu kadar yavaş olduğuna dair herhangi bir fikrin var mı? Bu bir böcek gibi geliyor.
groupedyoksa :)), basitlik baskın faktördür. Standart kitaplık için kararlılık ve performans zarafetten üstün olmalıdır. Ancak hem Scala'da Programlama'da hem de normal özyinelemeli (kuyruk özyinelemeli yerine) çağrıların standart kitaplıklarında birçok örnek vardır ; FP araç kutusundaki standart ve önemli bir silahtır.
Kuyruk özyinelemeye karşı özyinelemeye karşı bazı tartışmalar olduğundan, bölme yönteminin bir kuyruk özyinelemeli versiyonunu ekliyorum. Tailrec açıklamasını, uygulamanın gerçekten tail-recusive olmaması durumunda derleyiciyi şikayet etmeye zorlamak için kullandım. Kuyruk özyinelemesinin kaputun altında bir döngüye dönüştüğüne ve yığın sonsuza kadar büyümeyeceğinden büyük bir liste için bile sorun yaratmayacağına inanıyorum.
import scala.annotation.tailrec
object ListSplitter {
def split[A](xs: List[A], n: Int): List[List[A]] = {
@tailrec
def splitInner[A](res: List[List[A]], lst: List[A], n: Int) : List[List[A]] = {
if(lst.isEmpty) res
else {
val headList: List[A] = lst.take(n)
val tailList : List[A]= lst.drop(n)
splitInner(headList :: res, tailList, n)
}
}
splitInner(Nil, xs, n).reverse
}
}
object ListSplitterTest extends App {
val res = ListSplitter.split(List(1,2,3,4,5,6,7), 2)
println(res)
}