我可以使用array_map等数组函数设置数组的键

时间:2015-06-16 10:00:32

标签: php arrays functional-programming iterator array-map

我非常喜欢使用数组映射从另一个对象数组创建对象数组的函数式编程风格。

$newObjects = array_map(
  function($oldObject) {
    return new NewObject($oldObject);
  },
  $oldObjects
);

哪一个都运行正常,但我真的希望能够设置数组的索引,使它们是原始对象的id,以便于从数组中搜索和检索,但我想不出怎么做呢?这不是那么优雅。

$newObjects = array();
foreach ($oldObjects as $oldObject) {
  $newObjects[$oldObject->getId()] = new NewObject($oldObject);
}

我有办法做到这一点吗?

4 个答案:

答案 0 :(得分:2)

那就是 - array_reduce()正是你所需要的:

class Bar 
{
        protected $id;

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

        public function getId()
        {
                return $this->id;
        }
}

class Foo
{
        protected $bar;

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

$oldObjects = [new Bar('x'), new Bar('y'), new Bar('z')];

$newObjects = array_reduce($oldObjects, function($current, Bar $obj) {
        $current[$obj->getId()] = new Foo($obj);
        return $current;
}, []);

这将完成所有操作,而无需在array_combine()

之类的其他数组上花费内存

但是,我建议在必要时使用这些结构。使用它只是因为它看起来更好"可能不是一个好主意 - 因为普通循环在大多数情况下更具可读性。

答案 1 :(得分:1)

如果您使用array_walk和带有新索引的临时数组,该怎么办?

    $array = ['A', 'B', 'C', 'D'];
    $reIndexedTemp = [];

    array_walk(
        $array,
        function ($item, $key) use (&$reIndexedTemp) {
            // here you can have your logic to assemble your new index
            $reIndexedTemp[$key + 100] = $item;
        }
    );

    //$array = $reIndexedTemp;

    var_dump($array, $reIndexedTemp);

输出(没有注释行):

array(4) {
  [0] =>
  string(1) "A"
  [1] =>
  string(1) "B"
  [2] =>
  string(1) "C"
  [3] =>
  string(1) "D"
}
array(4) {
  [100] =>
  string(1) "A"
  [101] =>
  string(1) "B"
  [102] =>
  string(1) "C"
  [103] =>
  string(1) "D"
}

答案 2 :(得分:1)

我认为在这种情况下,foreach可能是最具可读性的解决方案,但您可以将array_map()array_combine()一起使用来实现您想要的效果。类似的东西:

// empty array to store the old object ids
$ids = [];

// map over old objects, inheriting $id 
// from parent scope by reference 
$objs = array_map(function($oldObject) use (&$ids) {
    $ids[] = $oldObject->getId();
    return new NewObject($oldObject);
}, $oldObjects);

// combine id and object arrays
$newObjects = array_combine($ids, $objs);

希望这会有所帮助:)

答案 3 :(得分:0)

环顾四周 - Looking for array_map equivalent to work on keys in associative arrays

建议使用array_combine

所以我猜它会是

$newObjects = array_combine(
  array_map(
    function($oldObject) {
      return $oldObject->getId();
    },
    $oldObjects
  ),
  array_map(
    function($oldObject) {
      return new NewObject($oldObject);
    },
    $oldObjects
  )
);

嗯可能是最好的,只是夸张的这一面,但肯定比foreach复杂得多