split a stream in many

后端 未结 6 1635
清酒与你
清酒与你 2021-01-05 07:46

I\'d like to know if there a elegant way to achieve something like that:

val l = Stream.from(1)

val parts = l.some_function(3)  //any number

parts.foreach(         


        
6条回答
  •  情深已故
    2021-01-05 08:37

    A simple approach involves generating an arithmetic sequence for the indices you want and then mapping that to the stream. The apply method will pull out the corresponding values:

    def f[A]( s:Stream[A], n:Int ) =
      0 until n map ( i => Iterator.iterate(0)(_+n) map ( s drop i ) )
    
    f( Stream from 1, 3 ) map ( _ take 4 mkString "," )
    // Vector(1,4,7,10, 2,5,8,11, 3,6,9,12)
    

    A more performant solution would employ an iterator whose next method simply returns the value from the stream at the next index in the arithmetic sequence:

    def comb[A]( s:Stream[A], first:Int, step:Int ):Iterator[A] = new Iterator {
      var i       = first - step
      def hasNext = true
      def next    = { i += step; s(i) }
    }
    def g[A]( s:Stream[A], n:Int ) =
      0 until n map ( i => comb(s,i,n) )
    
    g( Stream from 1, 3 ) map ( _ take 4 mkString "," )
    // Vector(1,4,7,10, 2,5,8,11, 3,6,9,12)
    

    You mentioned that this was for actors, though -- if this is Akka, perhaps you could use a round-robin router.

    UPDATE: The above (apparently incorrectly) assumes that there could be more work to do as long as the program is running, so hasNext always returns true; see Mikhail's answer for a version that works with finite streams as well.

    UPDATE: Mikhail has determined that this answer to a prior StackOverflow question actually has an answer that works for finite and infinite Streams (although it doesn't look like it would perform nearly as well as an iterator).

提交回复
热议问题