Matt Herbstritt
Matt Herbstritt

Reputation: 4862

PHP: Why missing values in associative array?

Can someone please put me out of my misery and explain why I'm missing the middle value when I try to push the results of a preg_match into another array? It's either something silly or a vast gap in my understanding. Either way I need help. Here is my code:

<?php 

$text = 'The group, which gathered at the Somerfield depot in Bridgwater, Somerset, 
        on Thursday night, complain that consumers believe foreign meat which has been 
        processed in the UK is British because of inadequate labelling.';

$word = 'the';

preg_match_all("/\b" . $word . "\b/i", $text, $matches, PREG_OFFSET_CAPTURE);

$word_pos = array();


for($i = 0; $i < sizeof($matches[0]); $i++){

    $word_pos[$matches[0][$i][0]] = $matches[0][$i][1];

}



    echo "<pre>";
    print_r($matches);
    echo "</pre>";

    echo "<pre>";
    print_r($word_pos);
    echo "</pre>";

?>

I get this output:

Array
(
[0] => Array
    (
        [0] => Array
            (
                [0] => The
                [1] => 0
            )

        [1] => Array
            (
                [0] => the
                [1] => 29
            )

        [2] => Array
            (
                [0] => the
                [1] => 177
            )

    )

)
Array
(
[The] => 0
[the] => 177
)

So the question is: why am I missing the [the] => 29? Is there a better way? Thanks.

Upvotes: 1

Views: 289

Answers (3)

MD. Sahib Bin Mahboob
MD. Sahib Bin Mahboob

Reputation: 20534

What is happening actually :

when i=0,
$word_pos[The] = 0   //mathches[0][0][0]=The 
when i=1
$word_pos[the] = 29       
when i=3
$word_pos[the] = 177  //here this "the" key overrides the previous one
                      //so your middle 'the' is going to lost :(

Now an array based solution can be like this :

for($i = 0; $i < sizeof($matches[0]); $i++){

    if (array_key_exists ( $matches[0][$i][0] , $word_pos ) ) {

        $word_pos[$matches[0][$i][0]] [] = $matches[0][$i][1];

    }

    else $word_pos[$matches[0][$i][0]] = array ( $matches[0][$i][1] );

}

Now if you dump $word_pos the output should be :

Array
(
[The] => Array
    (
    [0] => 0
        )
    [the] => Array 
        (
             [0] => 29 ,
             [1] => 177
        )
    )

Hope that helps.

Reference : array_key_exist

Upvotes: 1

Stefan
Stefan

Reputation: 2068

First you assign $word_pos["the"] = 29 and then you OVERWRITE IT with $word_pos["the"] = 177.

You don't overwrite The because indexes are case sensitive.

So maybe use an array of objects like this:

$object = new stdClass;
$object->word = "the"; // for example
$object->pos = 29; // example :)

and assign it to an array

$positions = array(); // just init once
$positions[] = $object;

alternatively you can assign an associative array instead of the object, so it would be like

$object = array(
    'word' => 'the',
    'pos' => 29
);

OR assign the way you do, but instead of overwriting, just add it to an array, like:

$word_pos[$matches[0][$i][0]][] = $matches[0][$i][1];

instead of

$word_pos[$matches[0][$i][0]] = $matches[0][$i][1];

so you get something like:

Array
(
[The] => Array
      (
         [0] => 0
      )
[the] => Array
      (
         [0] => 29
         [1] => 177
      )
)

Hope that helps :)

Upvotes: 1

ThiefMaster
ThiefMaster

Reputation: 318558

PHP arrays are 1:1 mappings, i.e. one key points to exactly one value. So you are overwriting the middle value since it also has the key the.

The easiest solution would be using the offset as the key and the matched string as the value. However, depending on what you want to do with the results a completely different structure might be more appropriate.

Upvotes: 1

Related Questions