উপাদানগুলির স্থির সংখ্যার সাথে একাধিক তালিকায় তালিকাটি বিভক্ত করুন


119

সর্বাধিক এন আইটেমগুলির সাথে তালিকার উপাদানগুলির একটি তালিকা কীভাবে বিভক্ত করবেন?

উদাহরণস্বরূপ: 7 টি উপাদান সহ একটি তালিকা দেওয়া, 4 টি গ্রুপ তৈরি করুন, কম গ্রুপের সাথে সম্ভবত শেষ গ্রুপটি রেখে যান।

split(List(1,2,3,4,5,6,"seven"),4)

=> List(List(1,2,3,4), List(5,6,"seven"))

উত্তর:


213

আমি আপনি যা খুঁজছেন মনে grouped। এটি একটি পুনরুক্তি ফেরত দেয় তবে আপনি ফলাফলকে তালিকায় রূপান্তর করতে পারেন,

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))

25
স্কালার তালিকায় প্রতিটি কিছুর জন্য কিছু রয়েছে।
জে আতকিন

আমি একটি অদ্ভুত প্রশ্ন আছে। একই ক্ষেত্রে যদি আমি ডেটাটিকে সিকোয়েন্সে রূপান্তর করি তবে আমি একটি স্ট্রিম অবজেক্ট পাই। কেন এমন?
রক্ষীথ

2
@ রক্ষিত এটি আলাদা প্রশ্নের মতো মনে হচ্ছে। স্কালায় একটি রহস্যময় জিনোম রয়েছে যা একটি ডেটা কাঠামো চয়ন করে এবং এটি আপনার জন্য একটি স্ট্রিম বেছে নিয়েছিল। আপনি যদি একটি তালিকা চান, আপনার একটি তালিকার জন্য অনুরোধ করা উচিত, তবে আপনি কেবল জিনোমের রায়কে বিশ্বাস করতে পারেন।
অয়ন ফ্রিম্যান

12

স্লাইডিং পদ্ধতিটি ব্যবহার করে টাস্কটি করার আরও অনেক সহজ উপায় রয়েছে। এটি এইভাবে কাজ করে:

val numbers = List(1, 2, 3, 4, 5, 6 ,7)

আপনাকে বলুন যে আপনি তালিকাটি আকারের 3 টি ছোট তালিকাতে ভাঙ্গতে চান।

numbers.sliding(3, 3).toList

তোমাকে দিবে

List(List(1, 2, 3), List(4, 5, 6), List(7))

9

অথবা আপনি নিজের তৈরি করতে চাইলে:

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)
}

ব্যবহার করুন:

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))

সম্পাদনা করুন : 2 বছর পরে এটি পর্যালোচনা করার পরে, আমি এই প্রয়োগের সুপারিশ করব না যেহেতু sizeও (এন), এবং সুতরাং এই পদ্ধতিটি ও (এন ^ 2), যা বিল্ট-ইন পদ্ধতিটি বৃহত তালিকার জন্য দ্রুততর হয়ে ওঠে তা ব্যাখ্যা করবে, নীচে মন্তব্য হিসাবে উল্লিখিত। আপনি নিম্নলিখিত হিসাবে দক্ষতার সাথে প্রয়োগ করতে পারেন:

def split[A](xs: List[A], n: Int): List[List[A]] =
  if (xs.isEmpty) Nil 
  else (xs take n) :: split(xs drop n, n)

বা এমনকি (সামান্য) আরও দক্ষতার সাথে ব্যবহার করে 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)
  }

4
xs splitAt nসংমিশ্রণের বিকল্প xs take nএবংxs drop n
কিপটন ব্যারোস

1
এটি স্ট্যাকটি বিস্ফোরিত করবে, পুনরাবৃত্তির বাস্তবায়ন বিবেচনা করবে
জেড ওয়েসলি-স্মিথ

কিপটন, সত্য, তবে আপনাকে অস্থায়ী ভ্যালায় ফলাফলগুলি বের করতে হবে যাতে এটি কোনও পদ্ধতিতে কয়েক লাইন যুক্ত করে। আমি একটি দ্রুত বেঞ্চমার্ক করেছি এবং এটি প্রায় 4% প্রায় পারফরম্যান্সের splitAtপরিবর্তে take/ dropউন্নত ব্যবহার করে বলে মনে হচ্ছে ; উভয়ই 700-1000% এর চেয়ে দ্রুত .grouped(n).toList!
লুইজি প্লিঞ্জ 21

@ লুইগি, বাহ grouped-toListএত ধীর কেন ? এটি বাগের মতো শোনাচ্ছে।
কিপটন ব্যারোস

@ জেড আপনি চরম ক্ষেত্রে ঠিক আছেন তবে আপনার বাস্তবায়ন আপনি এটি কী ব্যবহার করছেন তার উপর নির্ভর করে। ওপির ব্যবহারের ক্ষেত্রে (যদি groupedতা না থাকে :)), সরলতা হ'ল ওভাররাইডিং ফ্যাক্টর। স্ট্যান্ডার্ড লাইব্রেরির জন্য, স্থায়িত্ব এবং পারফরম্যান্সের উচিত কমনীয়তা। তবে স্কালায় প্রোগ্রামিং এবং সাধারণ-পুনরাবৃত্ত (পুচ্ছ-পুনরাবৃত্তির পরিবর্তে) কলগুলির স্ট্যান্ডার্ড লাইব্রেরি উভয়ই প্রচুর উদাহরণ রয়েছে ; এটি এফপি টুলবক্সের একটি মানক এবং গুরুত্বপূর্ণ অস্ত্র।
লুইজি প্লিঞ্জ

4

পুচ্ছ-পুনরাবৃত্তি বনাম পুনরাবৃত্তি নিয়ে কিছু আলোচনা হওয়ায় আমি বিভাজন পদ্ধতির একটি লেজ পুনরাবৃত্ত সংস্করণ যুক্ত করছি। বাস্তবায়ন যদি টেল-রিকুসিভ না হয় তবে আমি কম্পাইলারকে অভিযোগ করতে বাধ্য করার জন্য টেলরেক টীকাটি ব্যবহার করেছি। লেজ-পুনরাবৃত্তি আমার বিশ্বাস হুডের নীচে একটি লুপে পরিণত হয় এবং এটি বৃহত্তর তালিকার জন্য এমনকি সমস্যা তৈরি করে না কারণ স্ট্যাকটি অনির্দিষ্টকালের জন্য বৃদ্ধি পাবে না।

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)
}

1
এই উত্তরটি কিছু ব্যাখ্যা যুক্ত করে উন্নত করা যেতে পারে। গৃহীত উত্তরটি এটির ক্যানোনিকাল এবং ইচ্ছাকৃত উপায় বলে মনে হচ্ছে, আপনি কেন এই উত্তর পছন্দ করবেন তা ব্যাখ্যা করা উচিত।
জেফ্রি বসবুম

0

আমি মনে করি এটি গ্রহণ / ড্রপের পরিবর্তে স্প্লিটএট ব্যবহার করে বাস্তবায়ন

def split [X] (n:Int, xs:List[X]) : List[List[X]] =
    if (xs.size <= n) xs :: Nil
    else   (xs.splitAt(n)._1) :: split(n,xs.splitAt(n)._2)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.