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

Rubyで.真面目にディレクトリツリーを作って処理しています.

ついでに,パスリストへの動的な追加(add)と,基準パス以下の仮想ファイル一覧の出力(lslR)を追加しました.

x = PathList.new("aaa/bbb", "aaa/ccc", "aaa/ddd/eee", "bbb/ddd/eee")
pp x.ls('aaa/')
=> ["bbb", "ccc", "ddd/"]
pp x.ls('aaa/ddd/')
=> ["eee"]

x.add('bbb/foo', 'bbb/bar', 'bbb/baz/hoge')
pp x.ls('bbb')
=> ["ddd/", "baz/", "foo", "bar"]
pp x.ls()
=> ["aaa/", "bbb/"]

pp x.lslR
=> ["aaa/bbb",
    "aaa/ccc",
    "aaa/ddd/eee",
    "bbb/ddd/eee",
    "bbb/baz/hoge",
    "bbb/foo",
    "bbb/bar"]

pp x.lslR('bbb')
=> ["bbb/ddd/eee", "bbb/baz/hoge", "bbb/foo", "bbb/bar"]
 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class PathList
  def initialize(*obj)
    @files = Hash.new {|hash, key| hash[key] = PseudoDir.new(key) }
    self.add(*obj) unless obj.empty?
  end

  def add(*obj)
    obj.flatten.each do |path|
      path = path2list(path)
      @files[path[0]] += path[1..-1]
    end
    return self
  end

  def ls(path = '')
    path = path2list(path)
    return lscurdir if path.empty?
    return @files[path[0]].ls(path[1..-1])
  end

  def lslR(path = '')
    path = path2list(path)
    return @files[path[0]].lslR(path[1..-1]) unless path.empty?
    return self.traversal('')
  end

  def lscurdir
    @files.map {|name, file| file.name }
  end

  def traversal(prefix = '')
    @files.map do |name, file|
      file.traversal(prefix + self.name)
    end.flatten
  end

  def path2list(path)
    return path unless path.class == String     # XXX
    path.split(%r|/|)
  end

  def name
    ''
  end
end

class PseudoDir < PathList
  def initialize(name = nil)
    @name = name
    super()
  end

  def +(obj)
    name, rest = obj[0], obj[1..-1]
    return PseudoFile.new(@name) if obj.empty?

    @files[name] += rest
    return self
  end

  def name
    @name + '/'
  end
end

class PseudoFile < PathList
  attr_reader(:name)
  def initialize(name)
    @name = name
  end

  def +(obj)
    raise "#{self.name}: PseudoFile already exists"
  end

  def ls(list = [])
    return [] unless list.empty?  # No such file or directory
    return [self.name]
  end

  def traversal(prefix)
    return prefix + self.name
  end
end
__END__

正規表現です。grep に直接ブロックをわたし、Regexp.last_match をつかってみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def ls(pl, q)
    pl.grep(/^#{Regexp.quote(q)}\/?/) {|x|
        x.sub(Regexp.last_match[0], "").sub(/\/.+/, "/")
    }.delete_if {|i| i.empty? }
end

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

Index

Feed

Other

Link

Pathtraq

loading...