如何在 Rebol 2 中对列表进行分区

How to partition a list in Rebol 2

如何在 Rebol 2 中对列表进行分区?我不关心分区的最终顺序。

例如我想象会有这样的功能:

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

如果没有这样的内置函数,在 Rebol 中构造它的惯用方法是什么?

rebol.org/scripts/hof 上有一些 HOF, 例如实现你第二个愿望的配分函数

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

这是一个惯用的尝试:

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
]

用法示例:

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

将这些组合成一个函数很容易。这里有一些东西可以给你一些基本的想法:

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