Robert Corey February 2016

Searching an array of associate arrays for two matching parameters

I have a loop that builds an array of associative arrays that looks like this:

array(
    'foo' => '',
    'bar' => '',
    'thingys' => array()
)

on each iteration of the loop, I want to search through the array for an associate array that's 'foo' and 'bar' properties match those of the current associate array. If it exists I want to append the thingys property of the current associative array to the match. Otherwise append the entire thing. I know how to do this with for loops, but I'm wondering if there is a simpler way to do this with an array function. I'm on php 5.3.

Example

<?php 
$arr = array(
    array(
        'foo' => 1,
        'bar' => 2,
        'thing' => 'apple'
    ),
    array(
        'foo' => 1,
        'bar' => 2,
        'thing' => 'orange'
    ),
    array(
        'foo' => 2,
        'bar' => 2,
        'thing' => 'apple'
    ),
);

$newArr = array();
for ($i=0; $i < count($arr); $i++) {
    $matchFound = false;
    for ($j=0; $j < count($newArr); $j++) { 
        if ($arr[$i]['foo'] === $newArr[$j]['foo'] && $arr[$i]['bar'] === $newArr[$j]['bar']) {
            array_push($newArr[$j]['thing'], $arr[$i]['things']);
            $matchFound = true;
            break;
        }
    }
    if (!$matchFound) {

        array_push($newArr,
            array(
                'foo' => $arr[$i]['foo'],
                'bar' => $arr[$i]['bar'],
                'things' => array($arr[$i]['thing'])
            )
        );
    }
}

/*Output
$newArr = array(
    array(
        'foo' => 1,
        'bar' => 2,
        'things' => array('orange', 'apple')
    ),
    array(
        'foo' => 2,
        'bar' => 2,
        'things' => array('apple')
    ),
)
*/
 ?>

Answers


fusion3k February 2016

I don't know if it is possible through a built-in function, but I think no. Something can be implemented through array_map, but anyway you have to perform a double loop.

I propose you a one-loop solution using a temporary array ($keys) as index of already created $newArr items, based on foo and bar; elements of original array are processed through a foreach loop, and if a $keys element with first key as foo value and second key as bar value exists, then the current thing value is added to the returned key index of $newArr, otherwise a new $newArray element is created.

$newArr = $keys = array();
foreach( $arr as $row )
{
    if( isset( $keys[$row['foo']][$row['bar']] ) )
    { $newArr[$keys[$row['foo']][$row['bar']]]['thing'][] = $row['thing']; }
    else
    {
        $keys[$row['foo']][$row['bar']] = array_push( $newArr, $row )-1;
        $newArr[$keys[$row['foo']][$row['bar']]]['thing'] = array( $row['thing'] );
    }
}
unset( $keys );

eval.in demo

Edit: array_map variant

This is the same solution above, using array_map instead of foreach loop. Note that also your original code can be converted in this way.

$newArr = $keys = array();
function filterArr( $row )
{
    global $newArr, $keys;
    if( isset( $keys[$row['foo']][$row['bar']] ) )
    { $newArr[$keys[$row['foo']][$row['bar']]]['thing'][] = $row['thing']; }
    else
    {
        $keys[$row['foo']][$row['bar']] = array_push( $newArr, $row )-1;
        $newArr[$keys[$row['foo']][$row['bar']]]['thing'] = array( $row['thing'] );
    }
}

array_map( 'filterArr', $arr );

eval.in demo

Post Status

Asked in February 2016
Viewed 1,962 times
Voted 9
Answered 1 times

Search




Leave an answer