LoginSignup
1
1

More than 5 years have passed since last update.

複数のパスの共通のプリフィクスを求める

Last updated at Posted at 2012-09-25
# -*- coding: utf-8 -*-
require 'pp'

# 簡単のため、フルパスのみを扱う。
paths = %w[
  /full/path/to/somewhere
  /full/path/to/anywhere
  /full/path/to/nowhere
  /full/path/to
]

# 単位に分割する。
parts_list = paths.map {|path| path.split('/')}
pp parts_list
# => [["", "full", "path", "to", "somewhere"],
#     ["", "full", "path", "to", "anywhere"],
#     ["", "full", "path", "to", "nowhere"],
#     ["", "full", "path", "to"]

# 要素数が最大の物を一つ選ぶ。このあとで使うArray#zipでは、結果配列の各要素の長さがレシーバーの長さに制限されるから。
# 何を言っているか分からないと思うのでるりまを見られたい。
base = parts_list.max_by(&:length)
parts_list.delete base
p base # => ["", "full", "path", "to", "somewhere"]
pp parts_list
# => [["", "full", "path", "to", "anywhere"],
#     ["", "full", "path", "to", "nowhere"],
#     ["", "full", "path", "to"]]

# zipメソッドで、各階層のタプルを作る。
zipped = base.zip(*parts_list)
pp zipped
# => [["", "", "", ""],
#     ["full", "full", "full", "full"],
#     ["path", "path", "path", "path"],
#     ["to", "to", "to", "to"],
#     ["somewhere", "anywhere", "nowhere", nil]]

# 順番に調べて、行って、タプルの全要素が等くない物が出てきたらやめる。
commons = zipped.take_while {|tuple| tuple.uniq.length == 1}
pp commons
# => [["", "", "", ""],
#     ["full", "full", "full", "full"],
#     ["path", "path", "path", "path"],
#     ["to", "to", "to", "to"]]

# 結果を元のパスの形に戻せば望みのパスが得られる。
common_prefix = commons.collect {|tuple| tuple.first}.join('/')
puts common_prefix
# => /full/path/to

なんか名前の付いた有名なアルゴリズムがありそうなんですけど、どうなんでしょう。
教えてください。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1