PHP remove similar arrays based on several associations in an associative array

Go To StackoverFlow.com

1

I have this type of associative array.

Array
(
 [0] => Array
    (
        [bookedArea] => Comp Pool
        [laneBooked] => 1
        [paidBy] => Edmonton Aurora Synchronized Swim Club
        [startTime24hr] => 16:00
        [finishTime24hr] => 18:00
    )

 [1] => Array
    (
        [bookedArea] => Comp Pool
        [laneBooked] => 2
        [paidBy] => Edmonton Aurora Synchronized Swim Club
        [startTime24hr] => 16:00
        [finishTime24hr] => 18:00
    )

 [2] => Array
    (
        [bookedArea] => Comp Pool
        [laneBooked] => 3
        [paidBy] => Keyano Swim Club
        [startTime24hr] => 16:00
        [finishTime24hr] => 18:00
    )
)

I would like to make a new array removing similar entries depending on several associations. startTime24hr, finishTime24hr bookedArea & paidBy if all 4 aren't the same then it shouldn't be removed. Plus I would like to capture the first and last lanes in the new associative array.

Array
  (
    [0] => Array
     (
        [bookedArea] => Comp Pool
        [firstLaneBooked] => 1
        [lastLaneBooked] => 2
        [paidBy] => Edmonton Aurora Synchronized Swim Club
        [startTime24hr] => 16:00
        [finishTime24hr] => 18:00
     )
    [2] => Array
     (
        [bookedArea] => Comp Pool
        [firstLaneBooked] => 3
        [lastLaneBooked] => 3
        [paidBy] => Keyano Swim Club
        [startTime24hr] => 16:00
        [finishTime24hr] => 18:00
     )
  )

I found this which would help me filter with only one association. However I need 3 more.

$copy = $array; // create copy to delete dups from the array you wish to filter from
$newFilteredArray = array(); // new filtered array.
$item1 = 'startTime24hr'; // the association you want to filter with.
for( $i=0; $i<count($array); $i++ ) {
    if ( in_array( $array[$i][$item1], $newFilteredArray ) ) {
        unset($copy[$i]);
    }
    else {
        $newFilteredArray [] = $array[$i][$item1]
    }
}
print_r($copy);

Edit ---- Thank you Alexander for helping me get the iterations correct.

I have been struggling with inserting into my filtered array the start and finish lanes. I have commented out my attempts to make it work. When its uncommented I get: Notice: Undefined index: startTime24hr and it seems like its in some infinite loop. But if you comment my stuff no Notices. Can anyone help with this? function array_push_assoc($array, $key, $value){ $array[$key][] = $value; return $array; }

$CPfilteredArray = array();
$lanes = 0;
for($i = 0; $i < count($compPoolArray); $i++) {
  $add = true;
  // $lanesAdded = false;
  // $lanes = $lanes + 1;
  // $startLane = $compPoolArray[$i]["laneBooked"];
  for($j = 0; $j < count($CPfilteredArray); $j++) {
    if(($compPoolArray[$i]["startTime24hr"] === $CPfilteredArray[$j]["startTime24hr"])
        && ($compPoolArray[$i]["finishTime24hr"] === $CPfilteredArray[$j]["finishTime24hr"])
        && ($compPoolArray[$i]["bookedArea"] === $CPfilteredArray[$j]["bookedArea"])
        && ($compPoolArray[$i]["paidBy"] === $CPfilteredArray[$j]["paidBy"])) {
            $add = false;
            // $lanes = $lanes + 1;
            // $lanesAdded = True;
    }
  }
    if($add) {
        $CPfilteredArray[] = $compPoolArray[$i];
        // if ($lanesAdded){
        //     $lastLane = $startLane + $lanes;
        //     $CPfilteredArray[$i] = array_push_assoc($CPfilteredArray, 'firstLane', $startLane);
        //     $CPfilteredArray[$i] = array_push_assoc($CPfilteredArray, 'lastLane', $lastLane);
        // }
        // else {
        //     $CPfilteredArray[$i] = array_push_assoc($CPfilteredArray, 'firstLane', $startLane);
        //     $CPfilteredArray[$i] = array_push_assoc($CPfilteredArray, 'lastLane', $startLane);
        // }
    }
}
2012-04-03 19:50
by CamSyl


1

Two loop cycles do the job.

$filteredArray = array();
for($i = 0; $i < count($array); $i++) {
  $add = true;
  for($j = 0; $j < count($filteredArray); $j++) {
    if(($array[$i]["startTime24hr"] === $filteredArray[$j]["startTime24hr"])
        && ($array[$i]["finishTime24hr"] === $filteredArray[$j]["finishTime24hr"])
        && ($array[$i]["bookedArea"] === $filteredArray[$j]["bookedArea"])
        && ($array[$i]["paidBy"] === $filteredArray[$j]["paidBy"])) {
       $add = false;
    }
  }
  if($add) $filteredArray[] = $array[$i];
}

The resulting array called $filteredArray contains the filtered elements.

2012-04-03 20:05
by Alexander
That worked like a charm. Thanks - CamSyl 2012-04-03 20:18


1

I know it doesn't really answer (not allowed to comment yet...) your question but if you're retrieving data from db, you could use a query to retrive grouped values. It could look sth like this (pseudo-SQL)

SELECT
     bookedArea
    ,paidBy
    ,startTime24hr
    ,finishTime24hr
    ,MIN(laneBooked)
    ,MAX(laneBooked)
FROM 
    reservation -- ??
WHERE
--condition
GROUP BY
    bookedArea
    ,paidBy
    ,startTime24hr
    ,finishTime24hr
2012-04-03 20:08
by BlindAndFurious
I'm attempting to not use a database just yet. Thanks tho - CamSyl 2012-04-03 20:46


1

If you do know what elements you use to merge array value you may also use a hashmap to do the merge on insertion. So once you add an element to the array you create a hash over

$bookings = array();
$hash = md5($arr['bookedArea'] . $arr['paidBy'] . $arr['startTime24hr'] . $arr['finishTime24hr']);
if ( array_key_exists($hash, $bookings) ){
    //add just another lane to the booking
}
else{
    //create a new booking entry
}

that way your code may be even more efficient.

2012-04-03 20:13
by MatthiasLaug
That looks very streamlined. I will play with this, I'm not entirely sure how it works tho. But I will look arraykeyexists up in php.net. Thank - CamSyl 2012-04-03 20:49
It is fairly easy. You create a hash and get via arraykeyexists the information wether there is arleady an item with the same information encoded in the hash. Further information may be found here http://en.wikipedia.org/wiki/Hash_tabl - MatthiasLaug 2012-04-06 12:16


1

This may also work: (You can replace the serialize function to only serialize selected elements)

<?php 

$arr=array(
        0=>array("a"=>1, "b"=>"hello"),
        1=>array("a"=>2, "b"=>"hellooo"),
        2=>array("a"=>1, "b"=>"hello"),
        );

function removeDuplicates( &$arr ){
    $index=array();
    $result=array();
    foreach ($arr as $key=>$val){
        $k=serialize($val);
        if(!isset($index[$k])){
            $index[$k]=$key;
            $result[$key]=$val;
        }
    }
    return $result;
}

$result=removeDuplicates($arr);

print_r($arr);
print '<br>';
print_r($result);
?>
2012-04-03 20:15
by jornare
Ads