challenge 擬似lsの実装

スラッシュで区切られた文字列の配列(以下パスリスト)がある。
このパスリストにたいして擬似的なlsを行いたい。
lsはパスリストと表示対象ディレクトリのパスを入力する。

例としては以下のようになる。
pathList = ["aaa/bbb","aaa/ccc","aaa/ddd/eee","bbb/ddd/eee"]

ls(pathList,"aaa/")
>["bbb","ccc","ddd/"]

ls(pathList,"aaa/ddd/")
>["eee"]

なおパスリストが大きくなったとき、速度がなるべく低下しないように実装するのが望ましい。
文字列は任意の文字コードであると仮定してかまわない。

Posted feedbacks - Scheme

問題文からは、第2引数はディレクトリ名である (したがって ls(pathList, "aaa/bbb") は空リストとなる)  と読めるのですがそれでいいでしょうか。lsの動作を考えると単独ファイルにマッチする場合も許しても良さそうですが、一応ディレクトリ名のみ許すことにしました。

gosh> (ls '("aaa/bbb" "aaa/ccc" "aaa/ddd/eee" "ddd/bbb/eee") "aaa/")
("bbb" "ccc" "ddd/")
gosh> (ls '("aaa/bbb" "aaa/ccc" "aaa/ddd/eee" "ddd/bbb/eee") "aaa/ddd/")
("eee")
gosh> (ls '("aaa/bbb" "aaa/ccc" "aaa/ddd/eee" "ddd/bbb/eee") "aaa/ddd")
("eee")
gosh> (ls '("aaa/bbb" "aaa/ccc" "aaa/ddd/eee" "ddd/bbb/eee") "aaa/bbb")
()

lsにはリストが渡されるので、クレバーなデータ構造をls内で毎回作ってもあまり速度に貢献しないだろうと判断。文字列マッチで済ませています。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(use srfi-1)
(use srfi-13)

(define (ls pathlist dir)
  (let* ((prefix (string-trim-right dir #[/]))
         (rx (string->regexp #`"^,(regexp-quote prefix)/")))
    (filter-map (lambda (p)
                  (and-let* ([m (rx p)])
                    (regexp-replace* (m'after) #/(?<=\/).*/ "")))
                pathlist)))

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env gosh

(use gauche.test)
(use srfi-1)

(define path-list (list "aaa/bbb" "aaa/ccc" "aaa/ddd/eee" "bbb/ddd/eee"))

(define (ls path-list dir)
  (define (matcher x)
    (and-let* ((rx (string->regexp #`"^,(regexp-quote dir)/?([^/]+/?)"))
               (m (rx x))
               (r (m 1)))
      r))
  (filter-map matcher path-list))

(test-start "path-list")
(test* "case '(ls path-list \"aaa/\")'"
       '("bbb" "ccc" "ddd/") (ls path-list "aaa/"))
(test* "case '(ls path-list \"aaa/ddd/\")'"
       '("eee") (ls path-list "aaa/ddd/"))
(test* "case '(ls path-list \"aaa/ddd\")'"
       '("eee") (ls path-list "aaa/ddd"))
(test* "case '(ls path-list \"aaa/bbb\")'"
       () (ls path-list "aaa/bbb"))
(test-end)

odzさんの#4465の指摘を見て修正。

gosh> (ls '("aaa/bbb/ccc" "aaa/bbb/ddd" "aaa/ccc/zzz") "aaa")
("ccc/" "bbb/")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
(use srfi-1)
(use srfi-13)

(define (ls pathlist dir)
  (let* ((prefix (string-trim-right dir #[/]))
         (rx (string->regexp #`"^,(regexp-quote prefix)/")))
    (fold (lambda (p rs)
            (or (and-let* ([m (rx p)]
                           [r (regexp-replace* (m'after) #/(?<=\/).*/ "")]
                           [ (not (member r rs)) ])
                  (cons r rs))
                rs))
          '() pathlist)))

Index

Feed

Other

Link

Pathtraq

loading...