【问题标题】:Call object member function on all array members对所有数组成员调用对象成员函数
【发布时间】:2016-05-10 13:42:35
【问题描述】:

这可能是一个有点愚蠢的问题,它的一个方便而不是功能。

假设我们有这个类:

class A { 
    public function getId() {
       return rand(0,100); //For simplicity's sake
    }
}

假设我们有一个A 类型的对象数组,例如$array = [ new A(), new A(), new A() ];

通常,如果我想将所有对象的数组转换为它们的 ID 数组,我会这样做:

$idArray = array_map(function ($a) { return $a->getId(); }, $array);

然而,这让我产生了一种简化它的强烈愿望(我经常使用它)。我想要这样的功能:

$idArray = magic_array_map('getId', $array);

我的问题是,有没有办法通过提供函数名称而不是实际回调来调用 array_map(或类似函数)?类似于array_map('count', $array) 但不是strlen 提供成员方法名称。

简而言之,有没有这种方式内置 PHP 或者我必须自己实现一个 array_map 来添加这个功能?

【问题讨论】:

    标签: php arrays callback


    【解决方案1】:

    你为什么不制作自己的函数并将其传递给array_map()?

    class A {
      public function getId() {
        return rand(0,100); //For simplicity's sake
      }
    }
    
    $array = [ new A(), new A(), new A() ];
    
    function getId(A $object) {
      return $object->getId();
    }
    
    $ids = array_map('getId', $array);
    print_r($ids);
    

    【讨论】:

    • 这基本上就是OP在问题中显示的内容;他们只是通过将 lambda 函数直接嵌入到 array-map 调用中来更方便地(一次性使用)。 OP 正在寻找的是一种不必每次都编写自己的函数的方法。也就是说,下次他们想调用一个不同的函数,因此提到了传入成员函数的名称
    • [如果您多次调用 same 成员函数,那么另一种解决方案是执行整个任务的函数:function getIds(array $array_of_a) { return array_map(function ($a) { return $a->getId(); }, $array_of_a)); }。用法:$ids = getIds($array);]
    【解决方案2】:

    一种解决方案是将技术 php call class function by string name (see final code snippet) 应用到将其映射到数组的函数中:

    function apply_member_function(string $method_name, array $array) :array {
        return array_map(function ($ob) {return $ob->$method_name();}, $array);
    }
    

    用法:

    $array_of_as = [ new A(), new A(), new A() ];
    $array_of_ids = apply_member_function('getId', $array_of_as);
    

    【讨论】:

      【解决方案3】:

      在我看来,一个优雅的解决方案是创建一个 Container 类,其中包含一个 map 方法。比如:

      class A { 
          public function getId() {
             return rand(0,100); //For simplicity's sake
          }
      }
      
      class Container
      {
          protected $elements;
      
          public function __construct($elements = array())
          {
              $this->elements = $elements;
          }
      
          public function map($method)
          {
              return array_map(function ($element) use ($method) {
                  return $element->$method();
              }, $this->elements);
          }
      }
      
      $container = new Container([new A(), new A(), new A()]);
      
      var_dump($container->map('getId'));
      

      结果会是这样的:

      array(3) { [0]=> int(70) [1]=> int(32) [2]=> int(90) }
      

      【讨论】:

      • 我喜欢这个。这不是我想要的,但它是一种优雅的面向对象的方法。
      • 根据我公司的个人经验,我建议不要这样做,制作我们自己的类数组类。创建自己的类不是 php 数组的缺点是 a) 你失去了与数组一起使用的内置功能的便利性,[你可以恢复 大多数 i> 其中通过实现ArrayAccess, Countable 和可选的IteratorAggregate] b) 维护者的未来混乱:有时您将不可避免地使用数组,其他时候使用您自己的类。这很糟糕,在像 php 这样的松散类型语言中。
      【解决方案4】:

      您可以创建自己的辅助函数来做您想做的事情。

      my_map_function($callback, $array) {
          return call_user_func_array(callback, $array);
      }
      
      my_callback_function($array) {
        //TODO
      }
      
      main() {
        $array = [1, 2, 3];
        $array = my_map_function('my_callback_function', $array);
      }
      

      类似的东西;)

      这里有更多information

      【讨论】:

      • 我可能没有正确解释。问题是回调函数本身是数组中每个对象的成员函数。我将在问题中添加更多信息。
      猜你喜欢
      • 1970-01-01
      • 2012-01-02
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多