Я нашел некоторые решения проблемы сортировки, которые у меня были, но код использует анонимные функции в PHP. Im, использующий версию 5.2.17, и я считаю, что анонимные функции не поддерживаются.
Как я могу изменить следующие блоки кода, чтобы я мог использовать их в PHP 5.2.17
$keys = array_flip($order); usort($items, function($a, $b) use($keys) { return $keys[$a['id']] - $keys[$b['id']]; });
из многомерного массива сортировки PHP другим массивом
А также
$sorted = array_map(function($v) use ($data) { return $data[$v - 1]; }, $order);
от PHP – Сортировка многомерного массива другим массивом
ОБНОВЛЕНИЕ: Одна из проблем заключается в том, что я не уверен, как используются переменные $ a, $ b и $ v. Поэтому я не уверен, как создавать нормальные функции, минуя функции анона.
Обе анонимные функции use
предложение use
для передачи переменных в локальную область.
Вы можете добиться того же, что и объектные методы, в которых объекты имеют эти переменные как свойства.
Внутри метода объекта вы можете получить к ним доступ.
$sorted = array_map(function($v) use ($data) { return $data[$v - 1]; }, $order);
Примерный объект сопоставления мог бы выглядеть так:
class MapObj { private $data; public function __construct($data) { $this->data = $data; } public function callback($v) { return $this->data[$v - 1]; } }
Как вы можете видеть, он имеет ту же функциональность, но просто написан в синтаксисе PHP 5.2.
И это использование:
$map = new MapObj($data); $callback = array($map, 'callback'); $sorted = array_map($callback, $order);
И вот как это работает. Обратные вызовы для объектных методов всегда записываются в виде array
с двумя членами, первый – экземпляр объекта, а второй – это имя метода объекта.
Естественно, вы можете расширить это, поместив функцию отображения в объект сопоставления, так что это более прямолинейно:
class MapObj { ... public function map(array $order) { $callback = array($this, 'callback'); return array_map($callback, $order); } }
Новое использование:
$map = new MapObj($data); $sorted = $map->map($order);
Как вы можете видеть, это может сделать использование немного более прямым. Должен признаться, мой метод имен не очень блестящий здесь, поэтому я оставляю место для ваших улучшений.
Другим преимуществом является то, что вы можете сделать видимость метода обратного вызова приватным.
Ситуация с передачей данных для работы в обратном вызове в качестве параметра функции сопоставления. Это потому, что вы написали, что у вас уже есть класс, который вы хотите использовать, но вы не можете коснуться конструктора. Таким образом, данный пример немного короток.
Вот еще один пример без использования конструктора, я удалил его:
class MyObj { private $data; private function callback($v) { return $this->data[$v - 1]; } public function map($order, $data) { $callback = array($this, 'callback'); $this->data = $data; return array_map($callback, $order); } }
Как вы можете видеть, конструктор больше не нужен для передачи $data
, но вместо этого он просто передается в метод map()
в качестве дополнительного параметра. Применение:
$myObj = new MyObj(....); // somewhere. // later on: $myObj->map($order, $data); // could be also: $this->map($order, $data);
Как вы можете видеть, как вы устанавливаете переменную частного члена, зависит от вас. Сделайте то, что подходит для работы.
Здесь у вас есть закрытие над $data
– на 100% невозможно переписать его без анонимной функции. Вот ближайшая возможная аппроксимация:
function _array_sort_callback($a, $b) { global $_array_sort_callback__keys; return $_array_sort_callback__keys[$a['id']] - $_array_sort_callback__keys[$b['id']]; } ... { $keys = array_flip($order); global $_array_sort_callback__keys; $_array_sort_callback__keys = $keys; usort($items, "_array_sort_callback"); }
Обратите внимание, что я префикс имени глобального, чтобы избежать столкновения. И имя функции, и глобальное имя должны быть уникальными в вашем приложении.
Кроме того, имейте в виду, что PHP 5.2.17 устарел и не поддерживается. Вы должны как можно скорее перейти от него.
Если вы хотите подражать закрытию, где вы моментальные снимки в определенное время, вы можете использовать простой базовый класс, чтобы служить контейнером для значений, а затем просто определить подклассы для реализации логики сравнения.
Непроверенные
// base class exists purely to capture the value of some variables at instantiation time // kinda like a closure class VarCapture { protected $vars; function __construct($vars) { $this->vars = $vars; } } class ItemComparer extends VarCapture { function compare($a, $b) { $keys = $this->vars['keys']; return $keys[$a['id']] - $keys[$b['id']]; } } class PluckMapper extends VarCapture { function pluck($v) { $data = $this->vars['data']; return $data[$v - 1]; } } $keys = array_flip($order); $ic = new ItemComparer(compact('keys')); $callable = array($ic, 'compare'); usort($items, $callable); $pm = new PluckMapper(compact('data')); $callable = array($mp, 'pluck'); $sorted = array_map($callable, $order);
Обратите внимание, что я использовал php callback psuedo type http://php.net/manual/en/language.types.callable.php
Вы также можете переписать его в анонимные функции до 5.3, a la create_function()
. Хотя функции create_function()
обычно не действуют как замыкания, вы можете использовать некоторые трюки (без использования глобальных переменных), чтобы заставить их работать как замыкания в некоторых ограниченных обстоятельствах. Вы кодируете закрытые переменные непосредственно в источник функции. Ограничения заключаются в том, что данные только идут в одну сторону; закрытые переменные могут быть только «простыми» типами данных, такими как числа, строки и массивы; и функции, созданные с помощью create_function
, никогда не освобождаются, утечка памяти; плюс это не очень эффективно. Но я думаю, что этого достаточно для вашего примера (предполагая, что вы используете только массивы и строки и т. Д.).
$keys = array_flip($order); usort($items, create_function('$a,$b', '$keys = '.var_export($keys,true).'; return $keys[$a["id"]] - $keys[$b["id"]]; '));
а также
$sorted = array_map(create_function('$v', '$data = '.var_export($data,true).'; return $data[$v - 1]; '), $order);
Тем не менее, более общее решение до 5.3 означает использование объекта и метода в качестве закрытия, как в ответе хакры.