PHPで、重複が同じ値を持つキーと値のペアのサブセットとして定義されているオブジェクトの配列内の重複を削除するにはどうすればよいですか?

マークハイトンリドリー

私は次の形式の配列を持っています:

class anim {
    public $qs;
    public $dp;
    public $cg;
    public $timestamp;
}
$animArray = array();

$myAnim = new anim();
$myAnim->qs = "fred";
$myAnim->dp = "shorts";
$myAnim->cg = "dino";
$myAnim->timestamp = 1590157029399;
$animArray[] = $myAnim;

$myAnim = new anim();
$myAnim->qs = "barney";
$myAnim->dp = "tshirt";
$myAnim->cg = "bird";
$myAnim->timestamp = 1590133656330;
$animArray[] = $myAnim;

$myAnim = new anim();
$myAnim->qs = "fred";
$myAnim->dp = "tshirt";
$myAnim->cg = "bird";
$myAnim->timestamp = 1590117032286;
$animArray[] = $myAnim;

$ animArrayの非重複(および重複が見つかった最新のエントリ)のみを含む新しい配列を作成するにはどうすればよいですか。重複は次のように定義されます。

一つは、ここで$myAnim->dp別の配列要素のと同じ値を有する$myAnim->dpAND$myAnim->cg第から$myAnim->cg第二互いに同じ値を持っているから。

上記の例では、最初の要素のみがその定義によって一意です。

エレガントな解決策があることを願っています。PHPマニュアルのすべての配列関数を試しましたが、どのように実現できるかわかりません。

各配列要素をループし$myAnim->dpて、別の配列要素の値と同じ値であるかどうか確認し$myAnim->dp、一致を新しい配列に保存してから、その新しい配列をループして、その新しい配列内の他の要素と$myAnim->cg一致するかどうか確認できます$myAnim->cg

より洗練されたソリューションでは、多くのコードを再キャストすることなく、キーと値のペアのどの組み合わせが重複があるかどうかを判断するように変更できます。

そのような解決策はありますか?

この初心者を助けてくれてありがとう:)

MatsLindh

箱から出して直接使用できる組み込みのものはありませんが、一意性を考慮するために任意の数のプロパティを処理するために必要なコードはそれほど多くありません。ルックアップ配列内の各一意のプロパティを追跡することにより、リーフノード(つまり、配列自体ではないノード)がオブジェクトである配列を構築できます。

これを行うに&は、配列内の現在のレベルへの参照()を保持してから、各プロパティのルックアップ配列の作成を続行します。

function find_uniques($list, $properties) {
    $lookup = [];
    $unique = [];
    $last_idx = count($properties) - 1;

    // Build our lookup array - the leaf nodes will be the items themselves,
    // located on a level that matches the number of properties to look at
    // to consider a duplicate
    foreach ($list as $item) {
        $current = &$lookup;

        foreach ($properties as $idx => $property) {
            // last level, keep object for future reference
            if ($idx == $last_idx) {
                $current[$item->$property] = $item;
                break;
            } else if (!isset($current[$item->$property])) {
                // otherwise, if not already set, create empty array
                $current[$item->$property] = [];
            }

            // next iteration starts on this level as its current level
            $current = &$current[$item->$property];
        }
    }

    // awr only calls the callback for leaf nodes - i.e. our items.
    array_walk_recursive($lookup, function ($item) use (&$unique) {
        $unique[] = $item;
    });

    return $unique;
}

上記のデータを使用して呼び出され、一意であり、重複の最後の要素が返されるという要件がある場合、次の結果が得られます。

var_dump(find_uniques($animArray, ['dp', 'cg']));

array(2) {
  [0] =>
  class anim#1 (4) {
    public $qs =>
    string(4) "fred"
    public $dp =>
    string(6) "shorts"
    public $cg =>
    string(4) "dino"
    public $timestamp =>
    int(1590157029399)
  }
  [1] =>
  class anim#3 (4) {
    public $qs =>
    string(4) "fred"
    public $dp =>
    string(6) "tshirt"
    public $cg =>
    string(4) "bird"
    public $timestamp =>
    int(1590117032286)
  }
}

例の要素[0]と要素[2]マップするもの。代わりに、最初のオブジェクトを重複のために保持したい場合は、プロパティ値がすでに表示されている場合に内部ループを終了するissetを追加します。

foreach ($properties as $idx => $property) {
    if ($idx == $last_idx) {
        if (isset($current[$item->$property])) {
            break;
        }

        $current[$item->$property] = $item;
    } else {
        $current[$item->$property] = [];
    }

    // next iteration starts on this level as its current level
    $current = &$current[$item->$property];
}

これは、一意性を確認する配列に配列自体が含まれていないことを前提に記述されていることに注意してください(プロパティを検索->array_walk_recursiveているためおよびではないものを見つけるために使用しているため)アレイ)。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ