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?

dukereg
  • 722
  • 5
  • 16

2 Answers2

3

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]
]
draegtun
  • 22,441
  • 5
  • 48
  • 71
  • It's hard to find documentation for Rebol words used inside dialects. Please confirm I am understanding it correctly: a sorted copy is parsed so that like elements are always found adjacent to one another, the outer "any" matches repeatedly until end of input, while the inner "copy" matches any number of instances of the same value and copies the result into a value that is passed into the outer "collect" using "keep/only". Yes? – dukereg Nov 19 '17 at 05:17
  • @dukereg - Correct. Though I would like to emphasise that ANY, in the PARSE dialect, matches 0 or more like `*` in regex. So SOME, not used in above example, matches 1 or more, like `+` in regex. – draegtun Nov 20 '17 at 15:29
  • 1
    @dukereg - Couple of useful PARSE links: http://www.rebol.com/docs/core23/rebolcore-15.html | https://github.com/gchiu/rebol.net/blob/master/wikipedia/Parse%20Project.wiki – draegtun Nov 20 '17 at 15:30
2

There are some HOFs on rebol.org/scripts/hof, e.g. a partition function for your second wish

partition: func [
    {Partition the series 'xs in two parts, 
    'success and 'failure - according to the 
    outcome of application of the predicate 'p 
    to all elements of 'xs. 
        ((a -+ logic) -+ [a] -> [[a] [a]]) }
    p [any-function!] 
    xs [series!]
    /local us vs result [block!] 
][ 
    us: copy [] 
    vs: copy [] 
    foreach k xs [ 
        either p :k [ 
            insert/only tail us :k 
        ][ 
            insert/only tail vs :k 
        ] 
    ] 
    result: copy [] 
    append/only result us 
    append/only result vs 
    result
]


>> partition func [a] [even? a] lst
== [[6 2] [1 5 5 5 1 3]]
sqlab
  • 6,412
  • 1
  • 14
  • 29