2015-09-07 34 views
2

我目前有兩個類。Php:把它變成一個遞歸函數

ArrayCompare類:

<?php 
namespace App\Tools\RegexExtract; 

class ArrayCompare 
{ 


    public function compare(Array $arrayToCompare) 
    { 

     $elementData = new ElementMetaData(); 
     $metaData = $elementData->extract($arrayToCompare[0], [], $initial=true); 

     foreach ($arrayToCompare as $currentElement) { 

      $metaData = $elementData->extract($currentElement, $metaData); 

     } 

     return $metaData; 

    } 

} 

它使用ElementMetaData

<?php 
/** 
* A class for extracting meta data from an element. 
*/ 

namespace App\Tools\RegexExtract; 

class ElementMetaData 
{ 

    public function extract($element, $metaDataToCompare = [], $initial = false) 
    { 

     if ($initial == true) { 
      $this->isInteger($element) ? $returnMetaData['isInteger'] = $this->isInteger($element) : null; 
      $returnMetaData['length'] = $this->length($element); 
     } 

     else { 

      $returnMetaData=$metaDataToCompare; 


     if ($returnMetaData != []) { 
      if (isset ($returnMetaData['isInteger']) && !$this->isInteger($element)) { 
       unset($returnMetaData['isInteger']); 

      } 
      if (isset ($returnMetaData['length']) && $this->length($element) != $returnMetaData['length']) { 
       unset($returnMetaData['length']); 

      } 

     } 
     } 

     return $returnMetaData; 


    } 

    private function isInteger($element) 
    { 
     return is_int($element); 
    } 

private function length($element) 
{ 
    return strlen($element); 

} 

} 

的基本功能是:

給出我有一個數組

$arr=[1,2,3]; 

我想獲得之間的「相似性」全部元素。根據數組我預定義......所以這將帶來這樣的結果:

$metaArray=['isInteger'=>true,'length'=>1]; 

,這將帶來剛剛長度相似:

$arr=[1,2,'D']; 
$metaArray=['length'=>1]; 

雖然這陣將提供一個空的結果[]

$arr=[1,2,'3D']; // result is [] since not all integers or not all of same length. 

現在我的解決方案不使用遞歸函數......但我確信它可以以某種方式使用。

此外,我想添加更多的「標準」....所以"isEmailAdress", "beginswithA" ....等......這將使我的if語句是一個恐怖......所以什麼是最好的策略/設計在這裏遵循的模式?

+1

我看不到你的任務任何遞歸模式。儘管你可以編寫任何順序摺疊作爲遞歸。問題:你需要這裏嗎? – dmitry

+0

很高興聽到這一點。我認爲有改進/表演的餘地。由於這些數組可能會很長......但如果有更好的方式進行可讀性設計模式路徑上的代碼管理,很高興聽到它。 – Confidence

+0

我沒有看到單獨的'ElementMetaData'類的任何需要,因爲它根本沒有狀態,只是以靜態方式調用'extract'。它不應該是一個類,整個事情可能只是在一個函數中實現,使用'if..elseif'或'case'來測試你的標準。特別是如果表現是一個問題。 – dmitry

回答

1

我看不出有任何需要遞歸在這裏,所以我就做了一個設計方案的建議:

實現每個標準爲一類:

abstract class Criterion { 

    protected $valid = true; 

    abstract public function initialize($value); 
    abstract public function check($value); 

    public function isValid() { 
     return $this->valid; 
    } 

} 

class Length extends Criterion { 

    protected $length; 

    public function initialize($value) { 
     $this->length = strlen($value); 
    } 

    public function check($value) { 
     if ($this->length != strlen($value)) { 
      $this->valid = false; 
     } 
    } 

} 

然後你做一個您的所有標準數組:

$criteria = [new Length, ...]; 
foreach ($criteria as $criterion) { 
    $criterion->initialize($values[0]); 
} 

慢慢消減下來,通過自己的價值觀:

foreach ($values as $value) { 
    foreach ($criteria as $criterion) { 
     $criterion->check($value); 
    } 
} 

$commonCriteria = array_filter($criteria, function (Criterion $criterion) { 
    return $criterion->isValid(); 
}); 
+0

效果很好。並且非常可讀。 – Confidence

2

@deceze擊敗了我的公平邊緣......但我仍然會發布我的解決方案,基本上工作原理相同。

abstract class abstractComparer 
{ 
    private $array; 
    private $result = true; 
    protected $name; 

    public function compareArray($array) 
    { 
     $current = null; 

     foreach ($array as $index => $value) 
     { 
      $this->result = $this->result && $this->compareValues($index, $current, $value); 
      $current = $value; 
     } 
    } 

    public function getResult() 
    { 
     return $this->result; 
    }  

    public function getName() 
    { 
     return $this->name; 
    } 

    public abstract function compareValues($index, $value1, $value2); 

    public abstract function getSuccessValue(); 
} 

class intComparer extends abstractComparer 
{ 
    protected $name = "isInteger"; 

    public function compareValues($index, $value1, $value2) 
    { 
     return is_int($value2); 
    } 

    public function getSuccessValue() 
    { 
     return true; 
    } 
} 

class lengthComparer extends abstractComparer 
{ 
    protected $name = "length"; 
    protected $length = 0; 

    public function compareValues($index, $value1, $value2) 
    { 
     $this->length = strlen($value2); 
     return $index == 0 || strlen($value1) == $this->length; 
    } 

    public function getSuccessValue() 
    { 
     return $this->length; 
    } 
} 

,做實際的處理是這樣的:

$temp = [1,2,3]; 

$comparers = [new intComparer(), new lengthComparer()]; 
$result = array(); 

foreach ($comparers as $comparer) 
{ 
    $comparer->compareArray($temp); 

    if ($comparer->getResult()) 
    { 
     $result[$comparer->getName()] = $comparer->getSuccessValue(); 
    } 
} 

//var_dump($result);