mkzyk
@mkzyk

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

3重ループを使わない、効率的な方法について

Q&A

Closed

解決したいこと

下記のようなデータがある場合に、どうすれば3重ループなどを使用せずに計算量を減らす方法で実現できるか知りたいです。
log(n^x)にならない方法を模索しています。

例)

  • 下記のように、Array Aがあるとします。
ArrayA
(
    [0] => Array
        (
            [IdList] => Array
                (    
                    [0] => Array
                        (
                            [Id] => ID2
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                        (
                    [1] => Array
                        (
                            [Id] => ID6
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                        (
                (
        )

    [1] => Array
        (
            [IdList] => Array
                (    
                    [0] => Array
                        (
                            [Id] => ID3
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                        (
                    [1] => Array
                        (
                            [Id] => ID9
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                        (
                (
        )
    ...
)
  • IDに属するValueを保持している、別のArray Bも存在しています。(keyはID名となっています)
ArrayB
(
    [ID1] => foo
    [ID2] => bar
    [ID3] => baz
)

やりたいこと

下記のようなデータに変更したいです。
もしArray Bに存在するIdが、Array A(ArrayA[i][IdList][j][Id])に存在する場合は、マッチしたIdが存在するArrayA[i][IdList][j]Valueなどとして挿入したいです。

Array
(
    [0] => Array
        (
            [IdList] => Array
                (    
                    [0] => Array
                        (
                            [Id] => ID2
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                            [Value]  => bar
                        (
                    [1] => Array
                        (
                            [Id] => ID6
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                        (
                (
        )

    [1] => Array
        (
            [IdList] => Array
                (    
                    [0] => Array
                        (
                            [Id] => ID3
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                            [Value]  => baz
                        (
                    [1] => Array
                        (
                            [Id] => ID9
                            [A]  => A
                            [B]  => B
                            [C]  => C
                            ...
                        (
                (
        )
    ...
)

自分で試したこと

下記のようにすれば可能だと思うのですが、他にもし効率のよい方法があればぜひ知りたいと思いました。

foreach($arrayA as $i => $data) {
  foreach($arrayA[$i] as $j => $id) {
    foreach($arrayB as $key => $value) {
      if($id === $key) {
        arrayA[$i]['IdList'][$j]['Value'] = $value;
      }
    }
  }
}
0

2Answer

2重ループにできた。

<?php

$arrayA = [
    ['IdList' => [
        ['Id' => 'ID1', 'A' => 'A', 'B' => 'B'],
        ['Id' => 'ID2', 'A' => 'A', 'B' => 'B'],
        ['Id' => 'ID4', 'A' => 'A', 'B' => 'B']
    ]],
    ['IdList' => [
        ['Id' => 'ID3', 'A' => 'A', 'B' => 'B'],
        ['Id' => 'ID5', 'A' => 'A', 'B' => 'B'],
        ['Id' => 'ID1', 'A' => 'A', 'B' => 'B']
    ]]
];

$arrayB = [
    'ID1' => 'foo',
    'ID2' => 'bar',
    'ID3' => 'baz',
    'ID9' => 'foobar'
];

$chocolate = [];
foreach (array_keys($arrayA) as $i) {
    foreach (array_keys($arrayA[$i]['IdList']) as $j) {
        $id = $arrayA[$i]['IdList'][$j]['Id'];
        $chocolate[$id][] = [$i, $j];
    }
}

foreach ($arrayB as $key => $value) {
    if (array_key_exists($key, $chocolate) === false) continue;
    foreach ($chocolate[$key] as $cacao) {
        [$i, $j] = $cacao;
        $arrayA[$i]['IdList'][$j]['value'] = $value;
    }
}

var_dump($arrayA);

?>
1Like

Comments

  1. @mkzyk

    Questioner

    早速のご回答ありがとうございます!
    なるほど、`array_keys`を使うのですね...!!
    勉強になりました!

これでいかがでしょう?

$arrayA = [
    [
        'IdList' => [
            ['Id' => 'ID1', 'A' => 'A', 'B' => 'B'],
            ['Id' => 'ID2', 'A' => 'A', 'B' => 'B'],
            ['Id' => 'ID4', 'A' => 'A', 'B' => 'B'],
        ],
    ],
    [
        'IdList' => [
            ['Id' => 'ID3', 'A' => 'A', 'B' => 'B'],
            ['Id' => 'ID5', 'A' => 'A', 'B' => 'B'],
            ['Id' => 'ID1', 'A' => 'A', 'B' => 'B'],
        ],
    ],
];

$arrayB = [
    'ID1' => 'foo',
    'ID2' => 'bar',
    'ID3' => 'baz',
    'ID9' => 'foobar',
];

$resultArray = [];

foreach($arrayA as $key => $data) {
    $result = [];
    $result['IdList'] = array_map(function($id) use($arrayB) {
        $value = $arrayB[$id['Id']] ?? null;

        if ($value) {
            $id['value'] = $value;
        }

        return $id;
    }, $data['IdList']);
    
    $resultArray[] = $result;
}

var_dump($resultArray);
1Like

Comments

  1. @mkzyk

    Questioner

    なるほどです...! array_map活用してみます!ありがとうございました!

Your answer might help someone💌