2

私が抱えていたソートの問題に対するいくつかの解決策を見つけましたが、コードは PHP で無名関数を使用しています。バージョン 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);

from PHP - 多次元配列を別の配列でソートする

更新: 問題の 1 つは、変数 $a、$b、および $v がどのように使用されているかわかりません。したがって、通常の関数を作成する方法がわからないため、アノン関数をバイパスします。

4

4 に答える 4

3

どちらの匿名関数も、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);

そして、それがどのように機能するかです。オブジェクト メソッドのコールバックは、常にarray2 つのメンバーを持つ の形式で記述されます。最初のメンバーはオブジェクト インスタンスで、2 番目のメンバーはオブジェクト メソッドの名前です。

当然、これを拡張してマッピング関数をマッピング オブジェクトに入れることができるので、より簡単になります。

class MapObj
{
    ...

    public function map(array $order) {
        $callback = array($this, 'callback');
        return array_map($callback, $order);
    }
}

新しい使い方:

$map = new MapObj($data);
$sorted = $map->map($order);

ご覧のとおり、これにより、使用法がもう少し簡単になります。正直に言うと、私のメソッドの命名法はここではそれほど素晴らしいものではありません。そのため、改善の余地を残しておきます。

もう 1 つの利点は、コールバック メソッドの可視性を非公開にできることです。


コールバックで使用するデータをパラメーターとしてマッピング関数に渡す状況。それは、利用したいクラスがすでにあると書いたからですが、コンストラクターに触れることはできません。したがって、与えられた例は少し短いです。

コンストラクターを使用しない別の例を次に示します。削除しました。

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

ご覧のとおり、プライベート メンバー変数を設定する方法はユーザー次第です。仕事に合ったことをする。

于 2012-11-27T17:37:17.450 に答える
0

ここにあるのはクロージャーです$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 は廃止され、サポートされていないことに注意してください。できるだけ早く移行する必要があります。

于 2012-11-27T17:36:52.903 に答える
0

特定の時間に変数のスナップショットを作成するクロージャーを模倣したい場合は、単純な基本クラスを使用して値のコンテナーとして機能させ、サブクラスを定義して比較ロジックを実装するだけです。

未テスト

// 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 のコールバック疑似型 http://php.net/manual/en/language.types.callable.phpを使用したことに注意してください。

于 2012-11-27T17:40:31.460 に答える