Simple sorting
[1/8] from: sjohnson::cornerstonepaymentsystems::com at: 25-Sep-2002 17:19
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Hi all,
Been off the list for a while because I just couldn't keep up with the volume of this
great living list! Quickie question:
How do I get the code, listing: sort read %., to sort alphabetically by directories first
then by filenames?
So, the result looks like this:
>> sort read %.
== [%dir1/ %dir2/ %dir3/ %file1 %file2 %file3]
I know I'm missing something easy here...maybe a sort option?
Regards,
Sean C. Johnson
-- Binary/unsupported file stripped by Listar --
-- Type: image/jpeg
-- File: image001.jpg
-- Desc: image001.jpg
[2/8] from: greggirwin:mindspring at: 25-Sep-2002 16:02
Hi Sean,
<< How do I get the code, listing: sort read %., to sort alphabetically by
directories first then by filenames? So, the result looks like this:
[%dir1/ %dir2/ %dir3/ %file1 %file2 %file3] >>
I don't know that there's a single switch to do something like that. Maybe
someone else knows a nifty trick I don't. In any case, I whipped this up
real quick to show how you *could* do it. It uses a function I have to split
blocks into sub-blocks based on predicates.
dir-file-sort: func [
{Returns the block of files with directories first, followed by
files, with each group sorted.}
block [any-block!]
/local result
][
result: copy []
foreach blk split block [:dir?] none [
append result sort blk
]
]
split: func [
{Applies each predicate to each element in blk and returns
a block of blocks with items partitioned by which predicate
they match. If an item doesn't match any predicate, it will
be in the last block. Only handles simple args right now.}
series [series!]
predicates [block!]
args
/local match result p
][
result: copy []
loop add length? predicates 1 [append/only result copy []]
repeat el series [
match: false
repeat i length? predicates [
; Have to use a temp var for the predicate here, in addition
to
; the result of the predicate call.
p: get predicates/:i
match: p :el either block? args [args/:i][args]
if match [
append result/:i :el
break
]
]
if not match [
append last result :el
]
]
result
]
;split [1 2 3.4 5.6 7 8.9] [integer? decimal?] none
;split [1 2 3.4 5.6 7 8.9 0 100] [lesser? greater?] [3 7]
;split [1 2 3.4 5.6 7 8.9 0 100] [lesser? greater?] 3
I only tested this briefly but it should give you a starting point if
nothing else.
BIG CAVEAT: DIR? needs full path info if you're working on a list of files
that aren't in the current directory.
HTH!
--Gregg
[3/8] from: carl:cybercraft at: 26-Sep-2002 12:42
On 26-Sep-02, Sean Johnson wrote:
> Content-Type: text/plain;
> charset="iso-8859-1"
<<quoted lines omitted: 10>>
> Regards,
> Sean C. Johnson
Sort has a compare refinement that allows you to use a function to
make a comparison, the idea being to return true or false depending
on a comparison of two values. (I think - I only used it for the
first time yesterday:) For instance, this sorts on strings from the
second character onwards...
>> blk: ["xccc" "yaaa" "zbbb"]
== ["xccc" "yaaa" "zbbb"]
>> sort/compare blk func [a b][(second a) < second b]
== ["yaaa" "zbbb" "xccc"]
So, expand on that to sort your directory. (My rushed attempt didn't
work, so I won't inflict it on you;) Note, if you seperate your
function, use...
sort/compare blk :my-function
Note the colon.
--
Carl Read
[4/8] from: al:bri:xtra at: 26-Sep-2002 13:51
Sean wrote:
> How do I get the code, listing: sort read %., to sort alphabetically by
directories first then by filenames?
I'd use something like this:
sort/compare probe read %/c/Rebol/ func [File1 [file!] File2 [file!]] [
if all [(#"/" = last File1) (#"/" <> last File2)] [return true]
if all [(#"/" <> last File1) (#"/" = last File2)] [return false]
File1 < File2
]
I'm almost sure that the sorting function could be improved.
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
[5/8] from: greggirwin:mindspring at: 26-Sep-2002 21:11
This is a resend. The original didn't seem to make it to the list.
Hi Sean,
<< How do I get the code, listing: sort read %., to sort alphabetically by
directories first then by filenames? So, the result looks like this:
[%dir1/ %dir2/ %dir3/ %file1 %file2 %file3] >>
I don't know that there's a single switch to do something like that. Maybe
someone else knows a nifty trick I don't. In any case, I whipped this up
real quick to show how you *could* do it. It uses a function I have to split
blocks into sub-blocks based on predicates.
dir-file-sort: func [
{Returns the block of files with directories first, followed by
files, with each group sorted.}
block [any-block!]
/local result
][
result: copy []
foreach blk split block [:dir?] none [
append result sort blk
]
]
split: func [
{Applies each predicate to each element in blk and returns
a block of blocks with items partitioned by which predicate
they match. If an item doesn't match any predicate, it will
be in the last block. Only handles simple args right now.}
series [series!]
predicates [block!]
args
/local match result p
][
result: copy []
loop add length? predicates 1 [append/only result copy []]
repeat el series [
match: false
repeat i length? predicates [
; Have to use a temp var for the predicate here, in addition
to
; the result of the predicate call.
p: get predicates/:i
match: p :el either block? args [args/:i][args]
if match [
append result/:i :el
break
]
]
if not match [
append last result :el
]
]
result
]
;split [1 2 3.4 5.6 7 8.9] [integer? decimal?] none
;split [1 2 3.4 5.6 7 8.9 0 100] [lesser? greater?] [3 7]
;split [1 2 3.4 5.6 7 8.9 0 100] [lesser? greater?] 3
I only tested this briefly but it should give you a starting point if
nothing else.
BIG CAVEAT: DIR? needs full path info if you're working on a list of files
that aren't in the current directory.
HTH!
--Gregg
[6/8] from: anton:lexicon at: 27-Sep-2002 14:14
You could also do it like this,
which does not use dir? and does not
use any extra functions:
dir: %./ ; current directory
result: copy []
dirs: copy []
files: copy []
foreach file read dir [
append either #"/" = last file [dirs][files] file
]
result: compose [(sort dirs) (sort files)]
I have found it handy to have the files and dirs
in separate blocks for other processing, so that
may make this way preferable.
Anton.
[7/8] from: carl:cybercraft at: 27-Sep-2002 20:12
I was sure sort/compare could be used, so I tried again and came up
with this...
dir-sort: func [a b][
either any [
all [#"/" = last a #"/" = last b]
all [#"/" <> last a #"/" <> last b]
][
a < b
][
#"/" = last a ; Change to b to place files first.
]
]
; To test...
dir: %./ ; Current directory.
result: sort/compare read dir :dir-sort
It'll fall over if there's a file without any characters to its name,
(is that likely to exist on any systems?), but otherwise it seems to
work.
Carl.
On 27-Sep-02, Anton wrote:
> You could also do it like this,
> which does not use dir? and does not
<<quoted lines omitted: 15>>
>> result looks like this: [%dir1/ %dir2/ %dir3/ %file1 %file2 %file3]
>>>>
--
Carl Read
[8/8] from: sjohnson:cornerstonepaymentsystems at: 27-Sep-2002 17:46
Thanks everybody for the suggestions! I popped Greg's two functions in my script and
it worked first time out. The others I have kept to study a bit. :)
---
Sean
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted