2

I have currently two classes.

the ArrayCompare class:

<?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;

    }

}

which uses the ElementMetaData class

    <?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);

}

}

the basic functionality is:

given I have an array

$arr=[1,2,3];

I want to get the "similarities" between ALL Elements. According to a an array i Predefine...so this would deliver this result:

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

and this would deliver just length as similarity:

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

While this array would deliver an empty result []

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

Now my solution does not use recursive functions...but I am sure it can be used somehow.

Also, I want to add more "criteria"....So "isEmailAdress", "beginswithA"....etc....and this would make my if statements a horror....so what is the best strategy/design pattern to follow here?

3
  • 1
    I cannot see any recursive patterns in your task. Though of course you could write any sequence folding as a recursion. The question: do you need this here? Commented Sep 7, 2015 at 12:35
  • Good to hear that. I thought there is room for emprovement/performance . Since those arrays can be long....But In case there are better ways for readability, code management on the design patterns path, would be glad to hear it. Commented Sep 7, 2015 at 12:38
  • I don't see any need for separate ElementMetaData class, because it has no state at all and serves just to call extract in static manner. It should not be a class, the whole thing may be implemented just in a single function, using if..elseif or case to test your criteria. Especially if performance is a concern. Commented Sep 7, 2015 at 13:02

2 Answers 2

2

@deceze beat me to it by fair margin... but I'll still post my solution that works basically with the same principles.

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;
    }
}

And do the actual processing like this:

$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);
Sign up to request clarification or add additional context in comments.

Comments

1

I don't see any need for recursion here, so I'll just make a suggestion for a design approach:

Implement each criterion as a class:

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;
        }
    }

}

You then make an array of all your criteria:

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

And slowly whittle them down through your values:

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.