PrimuS
PrimuS

Reputation: 2683

Search nested multidimensional array

I have a function that fills an array:

foreach ($request->get('ids') as $id) {
    $pdfArray['other']++; // Yes this is initialized
    $pdfArray['rows'][$i]['id'] = $schedule->getId();
    $pdfArray['rows'][$i]['date'] = $schedule->getStart()->format('d.m.Y');
    $pdfArray['rows'][$i]['dateSort'] = $schedule->getStart()->format('Y-m-d H:i');
    $pdfArray['rows'][$i]['from'] = $schedule->getStart()->format('H:i');
    $pdfArray['rows'][$i]['to'] = $schedule->getEnd()->format('H:i');
    $pdfArray['rows'][$i]['desc'] = $schedule->getDescription();
}

What I want to do

On each loop, I want to check if the array (so far) already has a desc entry equal to the current $schedule->getDescription() AND the same date as $schedule->getStart()->format('d.m.Y') (actually more, but let's keep it simple)

What I tried

public function recursive_array_search($needle,$haystack) {
    foreach($haystack as $key=>$value) {
        $current_key=$key;
        if($needle===$value OR (is_array($value) && $this->recursive_array_search($needle,$value) !== false)) {
            return $current_key;
        }
    }
    return false;
}

Source

I use it like that:

if ($this->recursive_array_search($schedule->getDescription(), $pdfArray['rows']) &&
    $this->recursive_array_search($schedule->getStart()->format('d.m.Y'), $pdfArray['rows'])){
       $pdfArray['ma'][$schedule->getId()]++;
}

but this is true when ANY of the start or desc are SOMEWHERE in the current array.

How would I check if desc is found and start is in the SAME $i level?

EDIT for example

Let's say I have 10 $ids to loop through. After 2 loops, the $pdfArray looks like this:

Array
(
[other] => 2
[rows] => Array
    (
        [0] => Array
            (
                [id] => 1
                [date] => 13.07.2016
                [dateSort] => 2016-07-13 08:00
                [from] => 08:00
                [to] => 09:00
                [desc] => TEST
            )

        [1] => Array
            (
                [id] => 2
                [date] => 12.07.2016
                [dateSort] => 2016-07-12 08:00
                [from] => 08:00
                [to] => 09:00
                [desc] => TEST
            )

    )

)

The next iteration has the following:

$schedule->getStart()->format('d.m.Y') => 12.07.2016

$schedule->getDescription() => TEST

So I want to have the info that the combination already exists in the array.

BUT

$schedule->getStart()->format('d.m.Y') => 12.07.2016

$schedule->getDescription() => TEST2

should NOT return true upon checking of it exists.

Upvotes: 1

Views: 61

Answers (3)

LSerni
LSerni

Reputation: 57388

Function version:

/** 
 * Find matches for $item into pdfArray.
 * Returns an index array, possibly empty if no matches.
 * @param $item      item to find
 * @param $rows      rows where to search
 */
function findPdfArrayMatches(array $item, array $rows) {
    return array_keys(
  array_filter(
    $rows,
    function ($entry) use ($item) {

      // These are the matching criteria. More than one row may match.

      return $entry['desc'] == $item['desc']
          && $entry['date'] == $item['date']
      ;

    }
  )
);
}

You could do like this, in the loop:

$item = [
    'id'        => $schedule->getId(),
    'date'      => $schedule->getStart()->format('d.m.Y'),
    'dateSort'  => $schedule->getStart()->format('Y-m-d H:i'),
    'from'      => $schedule->getStart()->format('H:i'),
    'to'        => $schedule->getEnd()->format('H:i'),
    'desc'      => $schedule->getDescription(),
];

$matches = findPdfArrayMatches($item, $pdfArray['rows']);

if (!empty($matches)) {
    ...do something with the matches:
    foreach ($matches as $match) {
        $pdfArray['rows'][$match]['Duplicate'] = true;
    }
}
// Add new item
$pdfArray['rows'][$i] = $item;

Upvotes: 1

trincot
trincot

Reputation: 350252

To test for a "duplicate" you can use this function:

function testPresence($pdfArray, $desc, $date) {
    foreach ($pdfArray["rows"] as $row) {
        if ($row["desc"] == $desc && $row["date"] == $date) return true;
    }
}

Example use:

echo testPresence($pdfArray, "TEST2", "12.07.2016") ? "Found" : "Not found"; // Not found
echo testPresence($pdfArray, "TEST", "12.07.2016") ? "Found" : "Not found"; // Found

In your original loop, you can use it as follows:

foreach ($request->get('ids') as $id) {
    if (testPresence($pdfArray, $schedule->getDescription(), 
                                $schedule->getStart()->format('d.m.Y')) {
        // We have a duplicate. Maybe skip this entry?:
        continue;
    }

    $pdfArray['other']++;
    $pdfArray['rows'][$i]['id'] = $schedule->getId();
    $pdfArray['rows'][$i]['date'] = $schedule->getStart()->format('d.m.Y');
    $pdfArray['rows'][$i]['dateSort'] = $schedule->getStart()->format('Y-m-d H:i');
    $pdfArray['rows'][$i]['from'] = $schedule->getStart()->format('H:i');
    $pdfArray['rows'][$i]['to'] = $schedule->getEnd()->format('H:i');
    $pdfArray['rows'][$i]['desc'] = $schedule->getDescription();
}

Upvotes: 1

dios231
dios231

Reputation: 726

try this at your validation function

    public function array_search($needle1, $needle2 ,$haystack) {
       foreach($haystack as $singleArray){  
          if (in_array($needle1, $singleArray) && in_array($needle2, $singleArray))
              return true;
           else
            continue;
        }
        return false;
    }

and invoke your recursive_array_search like this

if ($this->array_search($schedule->getStart(), $schedule->getDescription(), $pdfArray['rows'])
continue;//Or any other kind of logic you want. At this place you know that description and date staet exist in at your array level
$pdfArray['other']++; // Yes this is initialized
$pdfArray['rows'][$i]['id'] = $schedule->getId();
$pdfArray['rows'][$i]['date'] = $schedule->getStart()->format('d.m.Y');
$pdfArray['rows'][$i]['dateSort'] = $schedule->getStart()->format('Y-m-d H:i');
$pdfArray['rows'][$i]['from'] = $schedule->getStart()->format('H:i');
$pdfArray['rows'][$i]['to'] = $schedule->getEnd()->format('H:i');
$pdfArray['rows'][$i]['desc'] = $schedule->getDescription();

Upvotes: 1

Related Questions