phparraysarray-filter

Return arrays where arrays data inside them occurs only once


Given the following array of multiple arrays, I would like to return all arrays where their data isn't duplicated in other arrays. For example $a['test'] array should only contain arrays with keys 1,2,4,5,8 because their values aren't duplicated in other arrays. I am looking into array_filter function at the moment, but can't quite get it right. Thanks

$a['test'] = [
    1 => [
        'key_1' => 1,
        'key_2' => 2
    ],
    2 => [
        'key_1' => 7,
        'key_2' => 8
    ],
    3 => [
        'key_1' => 1,
        'key_2' => 2
    ],
    4 => [
        'key_1' => 5,
        'key_2' => 6
    ],
    5 => [
        'key_1' => 3,
        'key_2' => 4
    ],
    6 => [
        'key_1' => 1,
        'key_2' => 2
    ],
    7 => [
        'key_1' => 5,
        'key_2' => 6
    ],
    8 => [
        'key_1' => 9,
        'key_2' => 10
    ]
];

And this is how I would like the array to look like after processing

$a['test'] = [
    1 => [
        'key_1' => 1,
        'key_2' => 2
    ],
    2 => [
        'key_1' => 7,
        'key_2' => 8
    ],
    4 => [
        'key_1' => 5,
        'key_2' => 6
    ],
    5 => [
        'key_1' => 3,
        'key_2' => 4
    ],
    8 => [
        'key_1' => 9,
        'key_2' => 10
    ]
];

Solution

  • array_filter isn't terribly suited for this, because that looks at one array element at a time. You're better off loping over your input array and populating a helper array, where you use the combination of the key_1 and key_2 values as the key (encode them as JSON, to get a unique string value for each combination) - if an entry with the key combination for the current element already exists, then you don't add it again.

    foreach($a['test'] as $item) {
        $key = json_encode($item);
        if(!isset($helper[$key])) {
            $helper[$key] = $item;
        }
    }
    $a['test'] = array_values($helper);;
    
    print_r($a['test']);
    

    Result:

    Array
    (
        [0] => Array
            (
                [key_1] => 1
                [key_2] => 2
            )
    
        [1] => Array
            (
                [key_1] => 7
                [key_2] => 8
            )
    
        [2] => Array
            (
                [key_1] => 5
                [key_2] => 6
            )
    
        [3] => Array
            (
                [key_1] => 3
                [key_2] => 4
            )
    
        [4] => Array
            (
                [key_1] => 9
                [key_2] => 10
            )
    
    )
    

    If you need to retain the original array's indexes in the result, then stick them into the data as well, so that you can restore them from there afterwards.

    foreach($a['test'] as $akey => $item) {
        $key = json_encode($item);
        if(!isset($helper[$key])) {
            $helper[$key] = [$akey, $item];
        }
    }
    $a['test'] = array_combine(array_column($helper, 0), array_column($helper, 1));
    
    print_r($a['test']);
    

    Result:

    Array
    (
        [1] => Array
            (
                [key_1] => 1
                [key_2] => 2
            )
    
        [2] => Array
            (
                [key_1] => 7
                [key_2] => 8
            )
    
        [4] => Array
            (
                [key_1] => 5
                [key_2] => 6
            )
    
        [5] => Array
            (
                [key_1] => 3
                [key_2] => 4
            )
    
        [8] => Array
            (
                [key_1] => 9
                [key_2] => 10
            )
    
    )