rebolrebol2

How to partition a list in Rebol 2


How does one partition a listin Rebol 2? I don't care about final order of partitions.

e.g. I imagined there would be a function something like this:

lst: [1 5 6 5 5 2 1 3]

probe partition lst  ; Assuming identity function by default
[[1 1] [5 5 5] [6] [2] [3]]

probe partition/by lst even?
[[6 2] [1 5 5 5 1 3]]

If there is no such inbuilt function, what is the idiomatic way of constructing it in Rebol?


Solution

  • Here's an idiomatic attempt:

    partition-unique: func [
        s [block!]
        /local got more
    ][
        collect [
            parse sort copy s [
                any [
                    copy got [
                        set more skip
                        any more
                    ] (keep/only got)
                ]
            ]
        ]
    ]
    
    partition-by: func [
        s [block!]
        f [any-function!]
        /local result
    ][
        result: reduce [make block! 0 make block! 0]
        forall s [append pick result f s/1 s/1]
        result
    ]
    

    Usage example:

    >> lst: [1 5 6 5 5 2 1 3]
    == [1 5 6 5 5 2 1 3]
    
    >> partition-unique lst
    == [[1 1] [2] [3] [5 5 5] [6]]
    
    >> partition-by lst :even?
    == [[6 2] [1 5 5 5 1 3]]
    

    It's easy to combine these into one function. Here's something to give you the basic idea:

    partition: func [
        s [block!]
        /by f [any-function!]
    ][
        either by [partition-by s :f] [partition-unique s]
    ]