4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

再帰的に探索

Last updated at Posted at 2013-09-23

前回の続き
Ruby - select + mapを1つのメソッドで - Qiita [キータ]

いわゆる探索のコーディングスタイルについて。
ワイルドカードの使い方を良く知らない人が、指定ディレクトの中から条件に沿うファイル(ファイル名の最後が数値で終わる)を探して配列で返す関数を作りたいとする。

今まではこう書いていた。

def obtain_file_list(path=".", acc=[])
  Dir::glob("#{path}/*").each do |child_node|
    if FileTest.directory?(child_node)
      obtain_file_list(child_node, acc)
    else
      if child_node =~ /\d$/
        acc << child_node
      else
        acc
      end
    end
  end

  acc
end

p obtain_file_list("/usr/local/Cellar")

ただ、eachを使って変数の中身を変更するのがキモい。という価値感が出てきたので、
最近はflat_mapを使用した書き方をするようになってきた。

def obtain_file_list(path=".")
  Dir::glob("#{path}/*").flat_map do |child_node|
    if FileTest.directory?(child_node)
      obtain_file_list(child_node)
    else
      if child_node =~ /\d$/
        child_node
      else
        []
      end
    end
  end
end

p obtain_file_list("/usr/local/Cellar")

これだと、変数を一切破壊せずに実行できてキモい。

追記

slimymars がコメント 2日前
外のを壊したくないならEnumerable#injectとか。

なるほど。これはこれで、まだ言語化しにくい違和感が。

def obtain_file_list(path=".")
  Dir::glob("#{path}/*").inject([]) do |acc, child_node|
    if FileTest.directory?(child_node)
      acc + obtain_file_list(child_node)
    else
      if child_node =~ /\d$/
        acc << child_node
      else
        acc
      end
    end
  end
end

p obtain_file_list("/usr/local/Cellar")
4
5
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
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?