一道PHP面試題,求兩個文件的相對路徑

首先原題是這樣子的:

寫一個函數,計算出兩個文件的相對路徑,如 $a = '/a/b/c/d/d.php',$b = '/a/b/1/2/c.php'

計算出的$b相對於$a的相對路徑應該是:../../c/d

那麼對於網上給出的答案,看了看貌似只能針對題目中給出的那個路徑來計算,如果路徑一變化,類似下面這樣,那麼那些程序好像沒用了,當然有些是有用,但是還是報一些警告出來。。。。。

例如:

$a = '/a/b/c/d/e/f/g/h/e.php'

$b = '/a/b/1/2/c.php'

再例如:

$a = '/a/e.php'

$b = '/a/b/c/d/1/2/c.php'

再例如:

$a = '/a/b/c/d/d.php'

$b = '/a/b/c/d/c.php'

所以這個情況挺多的,不能僅僅看當下的需求!

首先還是說下這個題目的意圖吧,它的要求是求$b相對於$a的一個相對路徑,也就是說是個什麼意思呢。

就是從$b所給定的那個文件通過相對路徑的方式表示怎麼樣可以找到$a所對應的那個文件。就那題目給出的那個路徑來解釋,就是我們怎麼$b到達$a呢,那首先從$b出發需要“../”上一級目錄然後再“../”上一級目錄來到了“/a/b”這個目錄下,然後接着再從這個目錄下出發,連接上“/c/d”然後就來到了$a所對應的目錄。

也就是說,這個題目的主要任務是找到從$b到$a需要“上幾級”才能到達和$a具有相同目錄的地方,然後接着連接上$a接下來的那部分,那麼我們就得到了答案,所以題目的關鍵是找到底需要“上幾級”!

廢話不多說,直接看代碼:


/**
 * 計算$b相對於$a的相對路徑
 * @param string $a
 * @param string $b
 * @return string
 */
function getRelativePath($a, $b) {
	$relativePath = "";
	$pathA = explode('/', dirname($a));
	$pathB = explode('/', dirname($b));
	$n = 0;
	$len = count($pathB) > count($pathA) ? count($pathA) : count($pathB);
	do {
		if ( $n >= $len || $pathA[$n] != $pathB[$n] ) {
			break;
		}
	} while (++$n);
	$relativePath .= str_repeat('../', count($pathB) - $n);
	$relativePath .= implode('/', array_splice($pathA, $n));
	return $relativePath;
}
$res = getRelativePath($a, $b);
var_dump($res);


經過測試呢,上面列舉的情況都滿足。

那這段程序需要解釋的就是:

$len爲什麼需要求出$a和$b中路徑最少的一個?

那是因爲下面我們通過do{}while();循環來從0即起始路徑開始向下一直對比$a和$b的路徑,希望找到是從哪個路徑開始導致$a和$b不一樣了,也就是從找到了$a和$b路徑總共相同的路徑數是幾個了。那在尋找的過程中,如果出現$a和$b的路徑一直不相等那麼$n會一直增加導致陷入死循環,所以還需要另外一個條件,就是我們需要讓$n的最大值不能超過$a和$b中路徑最短的一個,爲什麼呢?因爲$n一旦大於了$len那說明有一個路徑已經結束了,那直到結束也沒有找到$a和$b不一樣的那個部分,那說明其中最短路徑的長度正好是他們路徑相同的數目。(多數其它程序就範了這個錯誤),也就不需要繼續找了,因爲我們已經找到了。

找到了相同路徑的個數之後,首先需要計算的是:從$b到$a到底需要幾個“../”,那麼計算方法就是用“count($pathB) - $n”,爲什麼呢?因爲$n表示路徑相同的數目,而“ count($pathB)”表示$b的路徑數,那麼相互一減就得到了不同的路徑數目也就是需要的幾個“../”,那麼減完之後的結果一定是大於等0的值,所以沒問題!

找到了從$b到$a需要幾個“../”之後的任務就是將這幾個“../”和$a中不同的路徑部分拼接一下就可以了,也就是代碼:$relativePath .= implode('/', array_splice($pathA, $n));

到此,結束!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章