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

やり方は多分 shiro さんと同じ。 プリプロセスありなら、内部でリストをソートするなりツリーを構築するなりするんだけど、リストを直接渡すという要求なら単純な手法かなぁ。 って、みんな思うことは一緒ですね。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import sys
import re
import itertools

def uniq(ls):
    return (k for k, g in itertools.groupby(ls))

def ls(pathList, dir):
    pat = re.compile('%s([^/]+/?)' % re.escape(dir))
    matches = itertools.ifilter(None, (pat.match(path) for path in pathList))
    return list(uniq(sorted([m.group(1) for m in matches])))

def main(args):
    pathList = 'aaa/bbb aaa/ccc aaa/ddd/eee bbb/ddd/eee'.split()
    print ls(pathList, 'aaa/')
    print ls(pathList, 'aaa/ddd/')

if __name__ == '__main__':
    main(sys.argv[1:])

効率は考えてません。
1
2
3
4
5
6
7
import re

ls = lambda list, dir: [re.findall(dir + '([^/]+/?)', s)[0] for s in list if s.startswith(dir)]

pathList = ["aaa/bbb","aaa/ccc","aaa/ddd/eee","bbb/ddd/eee"]
print ls(pathList, 'aaa/')
print ls(pathList, 'aaa/ddd/')

クロージャで実装してみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def create(path_list):
    root = {}
    for path in path_list:
        node = root
        for name in path.rstrip("/").split("/"):
            node = node.setdefault(name, {})
    def ls(path):
        node = root
        for name in path.rstrip("/").split("/"):
            node = node.get(name, None)
            if node is None:
                return []
        return [name + "/" if children else name \
            for name, children in node.iteritems()]
    return ls

ls = create(["aaa/bbb","aaa/ccc","aaa/ddd/eee","bbb/ddd/eee"])
print ls("aaa/")
print ls("aaa/ddd/")

#4465での指摘への対処。
1
2
3
4
5
6
7
import re

ls = lambda list, dir: dict.fromkeys([re.findall(dir + '([^/]+/?)', s)[0] for s in list if s.startswith(dir)]).keys()

pathList = ["aaa/bbb","aaa/ccc","aaa/ddd/eee","bbb/ddd/eee"]
print ls(pathList, 'aaa/')
print ls(pathList, 'aaa/ddd/')

Index

Feed

Other

Link

Pathtraq

loading...