のらりくらり

物理化学分野のポスドクです。プログラミング、読書、自転車などが好きです。

Tree表示をするHashの拡張メソッドを書いてみた

Hashクラスを拡張する形で、Dosのtree的な表示をするスクリプトを書いてみた。
これって、綺麗に表示させようとすると案外考え込んだ。

ハッシュを、キー:親要素、値:子要素の配列 で書き(ネストされている場合も可。詳しくは以下のソース参照)Hash#treeで実行。
これだと、相互参照とかしてると、スタックオーバーフローでエラーになるし、あと、違う階層のものでも、要素の名前がかぶってると、同じものとみられちゃう・・・だから、ファイルシステムを舐めて、この形式のハッシュにする・・・っていうのじゃ不都合があるわけで。
まぁ、いつか直そう。いつかww

以下、ソース。

class Hash
	def tree
		buf = String.new
		tree_ = Array.new
		if self[nil]
			return tree2(nil, 0, buf, tree_)
		else
			return "Can't find the root."
		end
	end

	def tree2(parent, nestlevel, buf, tree_)
		branch = String.new
		nestlevel.times do |lv|
			if tree_[lv]
				branch << "|    "
			else
				branch << "     "
			end
		end
		cnt = self[parent].count
		self[parent].each_with_index do |elem, idx|
			buf << branch
			if idx != cnt - 1
				tree_[nestlevel] = true
				buf <<  "|--- "
			else
				tree_[nestlevel] = false
				buf << "\\--- "
			end
			buf << "#{elem}\n"
			buf = tree2(elem, nestlevel + 1, buf, tree_) if self[elem]
		end
		return buf
	end
	private :tree2
end

if __FILE__ == $0
	#####	Test Code ####
	airlines = Hash.new
	airlines[nil] = ["ASIA", "North America", "Europe", "Australia"]
	#airlines[nil] = ["JPN", "USA", "CAN", "ENG", "AUS"]
	airlines["ASIA"] = ["JPN"]
	airlines["North America"] = ["CAN", "USA"]
	airlines["Europe"] = ["ENG", "FRA"]
	airlines["Australia"] = ["AUS"]
	airlines["JPN"] = ["JAL", "ANA", "JAS"]
	airlines["CAN"] = ["Air Canada", "Canadian Airlines", "West Jet"]
	airlines["ENG"] = ["British Airways"]
	airlines["AUS"] = ["Qantas Airways"]
	airlines["FRA"] = ["Air France"]
	puts airlines.tree
end

これを実行すると、

|--- ASIA
|    \--- JPN
|         |--- JAL
|         |--- ANA
|         \--- JAS
|--- North America
|    |--- CAN
|    |    |--- Air Canada
|    |    |--- Canadian Airlines
|    |    \--- West Jet
|    \--- USA
|--- Europe
|    |--- ENG
|    |    \--- British Airways
|    \--- FRA
|         \--- Air France
\--- Australia
     \--- AUS
          \--- Qantas Airways

にしても、テストコードなんでこんな例にしたんやろw