如何比较一个对象数组,并在匹配时合并共享属性的值?

时间:2017-04-12 19:16:44

标签: php class oop

背景

在我正在开发的项目中,我创建了一个Builder类,其中包含一些以不同方式构建其对象的方法。我们称之为CompanyBuilder

CompanyBuilder有三个负责构建的对象:CompanyEmployeeSkill。在每个汇编方法中,它会在每个对象中注入一些依赖项。

物件

这些是负责构建的对象,我知道这里有四个,但是有三个对象。

class Company {
    public $name;
    public $employees = array();

    public function __construct($name) {
        $this->name = $name;
    }
}

class Person {
    public $name;
}

class Employee extends Person {
    public $job;
    public $skills = array();
}

class Skill {
    public $name;

    public function __construct($name) {
        $this->name = $name;
    }
}

生成器

构建器中有三种方法旨在提供构建对象时的灵活性。产生这个问题的那个看起来像这样:

$company = $companyBuilder->buildCompany(
    'Acme',
    $dependency,
    $employee,
    array(
        $skillOne,
        $skillTwo,
        $skillThree
    )
);

这样做的结果是一个公司对象,一个员工具有一个或多个技能。这种方法符合业务目标。但是,有一个问题。

问题

当我有不同的Company对象时,会出现问题,这些对象包含相同的name属性。如果Company名称匹配,我想将员工合并到一个Company对象中。

我原本以为我可以创建一个mergeEmployees方法,可以使用func_get_args()作为参数接收不确定数量的Company个对象,这会将它们变成一个对象数组。我已经尝试this solution但它对我没用。

希望在该阵列中查找具有相同名称的公司并合并其员工。所以如果args数组看起来像这样:

Company Object
(
    [name] => Acme
    [employees] => Array
        (
            [0] => Employee Object
                (
                    [job] => Designer
                    [skills] => Array
                        (
                            [0] => Skill Object
                                (
                                    [name] => web
                                )

                            [1] => Skill Object
                                (
                                    [name] => ui
                                )

                        )

                    [name] => Jacob
                )

        )

)
Company Object
(
    [name] => Scholastic
    [employees] => Array
        (
            [0] => Employee Object
                (
                    [job] => Developer
                    [skills] => Array
                        (
                            [0] => Skill Object
                                (
                                    [name] => java
                                )

                            [1] => Skill Object
                                (
                                    [name] => c#
                                )

                        )

                    [name] => Steve
                )

        )

)
Company Object
(
    [name] => Acme
    [employees] => Array
        (
            [0] => Employee Object
                (
                    [job] => Designer
                    [skills] => Array
                        (
                            [0] => Skill Object
                                (
                                    [name] => ux
                                )

                            [1] => Skill Object
                                (
                                    [name] => css
                                )

                        )

                    [name] => Jacob
                )

        )

)

我如何对这一系列对象进行比较,发现Employee雅各布应该具备他的'  UX'和' CSS'并将其(可靠地)与他之前的Employee对象的技能合并?

我尝试过使用array_reduce(),但它对我不起作用 - 肯定会误用它,因为它打算:

  

使用回调函数

迭代地将数组减少为单个值

我想使用array_filter(),但它只传递回调函数中的一个项目,这不足以进行比较。除非我遗漏了什么。

做这样的事情的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

我建议使用buildCompany方法中的实现:

function buildCompany($companyName, $employeeName, $skills){
    //let's say existing companies are in $companies array
    $existingCompany = false;

    foreach($companies as $key => $company){
        if($company->name === $companyName){
            $existingCompany = true;

            $existingEmployee = false;
            foreach($company->employees as $keyE => $employee){
                if($employee->name === $employeeName){
                    $existingEmployee = true;
                    $employee->skills = array_unique(array_merge($employee->skills, $skills), SORT_REGULAR); //http://stackoverflow.com/questions/13469803/php-merging-two-array-into-one-array-also-remove-duplicates
                    break;
                }
            }

            if(!$existingEmployee){
                $company->employees[] = new Employee($employeeName, $skills); // add a constructor to the Employee, i see it's missing (or just not provided)
            }
        }
    }
    if(!$existingCompany){
        $temp = new Company($companyName);
        $temp->employees[] = new Employee($employeeName, $skills); // add a constructor to the Employee, i see it's missing (or just not provided)
        $companies[] = $temp;
    }
}