PHP: Why missing values in associative array? - php

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.

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.

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 :)

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

Related

Searching all values from a specific Index in multidimensional, associative Array in php by Index, not by value

with some help of this forum i found a way to get an array that perfectly fits my task. I ran into a follow-up problem tho:
I got the following example-array
Array (
[A] => Array (
[D] => Array (
[A] => Array (
[M] => Array (
[result] => ADAM )
[N] => Array (
[result] => ADAN )
)
)
)
[H] => Array (
[E] => Array (
[N] => Array (
[R] => Array (
[Y] => Array (
[result] => HENRY )
)
[N] => Array (
[E] => Array (
[S] => Array (
[result] => HENNES )
)
)
)
)
)
)
Where the Letters are Indexes and i end up with an result array for each name.
Now i am looking for a way to Search this array with a specific search-string and it should be possible from the 3rd Char on. So if i Search for 'ADA' i want to get the value from all following result-arrays which would be "ADAM" and "ADAN" as both follow on Array['A']['D']['A'].
I didnt have any trouble starting to search at the right Index but i cant figure out a way to access all 'result'-arrays. Only found ways to search for the final Value (ADAM, ADAN) but as statet im looking for all final values possible from my searchpoint.
So basically i want to get all Values from the result arrays following the last Char from my Search-String as Index of my Array. Hopefully that explanation points out what im looking for.
Thanks in Advance!
In short:
//my Input
$searchstring = 'ADA';
//Output i want
"ADAM", "ADAN";
//Input
$searchstring = 'ADAM';
//Output
"ADAM"
EDIT: I edited this question with my approach so far as a comment pointed out i should do this (thanks for that! ) so i tried to go this way:
When i had my Example-Array i tried to only select the necessary part of the structure:
$searchquery = 'HEN';
//Searchquery as Array
$check = str_split($searchquery);
//second isntance of the original array which is named $result
$finalsearch = $result;
foreach($check as $key) {
$finalsearch = $finalsearch[$key];
}
//check with output if i selected the right area
print_r($finalsearch);
Output i got from this:
Array ( [R] => Array ( [Y] => Array ( [result] => HENRY ) ) [N] => Array ( [E] => Array ( [S] => Array ( [result] => HENNES ) ) ) )
So i am in the right are of the structure.
then i tried to find ways to search for all Instances of the index 'result'.
i found the following functions and approaches that all enabled me to search for a specific value but not the indexes.
$newArray = array_values($finalsearch);
array-search($searchquery, $finalsearch);
That was the Point where i started turning in circles
First part is to find the start point for the list, this is just a case of looping over each character in the search string and moving onto that value in the array.
Once you have found the start point, you can use array_walk_recursive() which will only visit the leaf nodes - so this will only be the names (in this case), so create a list of all these nodes and return them...
function getEntry ( array $result, string $search ) {
for($i = 0; isset($search[$i]); $i++){
$result = $result[$search[$i]];
}
$output = [];
array_walk_recursive($result, function ( $data ) use (&$output) {
$output[] = $data;
});
return $output;
}
$searchstring = 'ADA';
print_r(getEntry($result, $searchstring));
which should give...
Array
(
[0] => ADAM
[1] => ADAN
)
This script first iterates over the keys containing the chars of $searchstring and if it has found it and no errors were thrown, it walks the array recursively to find all result keys to add it to the $result array. After that it implodes the $result array and echos it.
$searchstring = 'HE';
for( $i = 0; $i < strlen( $searchstring ); $i++ ) {
$sub = #( isset( $sub ) ? $sub[$searchstring[$i]] : $array[$searchstring[$i]] )
or die( 'no results found' );
}
array_walk_recursive( $sub, function( $value ) use ( &$results ) {
$results[] = $value;
});
echo implode( ', ', $results );

Combining different array cells to one array on match

I can not wrap my head around how to do the following. I have two different lenght and different dimensional arrays that I want to combine so that the result array will have arrays1 + array2 cell that did not match.
This should help you understand what I mean
$dbquery_results1[0][] = array("1","5","b99");
$dbquery_results1[1][] = array("4","12","www");
$dbquery_results1[2][] = array("10","32","ccc");
$dbquery_results1[3][] = array("7","142","xx");
$dbquery_results2[0][] = array("c","10");
$dbquery_results2[1][] = array("as","1");
$dbquery_results2[2][] = array("fe","7");
$dbquery_combination[0][] = array("1","5","b99","as");
$dbquery_combination[1][] = array("7","142","xx","fe");
What I would like to get done
$i=0;
while(!empty($dbquery_results1[$i][0])) {
If($dbquery_results1[$i][0] == $dbquery_results2[any of the dimensions here][2])
{
$dbquery_combination[] = $dbquery_results1[$i][]+ $dbquery_results2[x-dimension][2];
} $i++;
}
So only if array1 has at [][0] same value as array2 [any dimension][1] will array1 + the array2 cell that is different be saved at array3.
Sorry that I am not too good expressing myself. Thanks a lot in advance.
So if you don't have the choice you can do it like this :
<?php
$dbquery_results1[0] = array("1","5","b99");
$dbquery_results1[1] = array("4","12","www");
$dbquery_results1[2] = array("10","32","ccc");
$dbquery_results1[3] = array("7","142","xx");
$dbquery_results2[0] = array("c","10");
$dbquery_results2[1] = array("as","1");
$dbquery_results2[2] = array("fe","7");
foreach($dbquery_results1 as $line_r1)
{
foreach($dbquery_results2 as $line_r2)
{
if($line_r1[0] == $line_r2[1])
{
$line = $line_r1;
$line[] = $line_r2[0];
$dbquery_combination[] = $line;
}
}
}
print_r($dbquery_combination);
?>
And the result is :
Array (
[0] => Array ( [0] => 1 [1] => 5 [2] => b99 [3] => as )
[1] => Array ( [0] => 10 [1] => 32 [2] => ccc [3] => c )
[2] => Array ( [0] => 7 [1] => 142 [2] => xx [3] => fe )
)
I think you are complicating the problem. I suppose that your array are the result of SQL request ? If it's the case, you should prefer to use joint SQL request.
//Coment Answer : Are they on the same server ? If yes, you can make request on multiple database at the same time by specifying full qualification.

PHP extract array values with the same key into another array

I have an array as so:
$diff_date_results =
Array (
[0] => Array ( [differential] => 7.7 [date] => 2012-12-30 )
[1] => Array ( [differential] => 8.2 [date] => 2012-12-31 )
[2] => Array ( [differential] => 9.9 [date] => 2013-01-03 )
)
I would like to extract all values from the differential key of each of the inner arrays to use the array_sum function on the newly created array.
I have this, which draws out the three numbers for me, but I get php errors for each number as an undefined index. (Notice: Undefined index: 7.7 in C:\wamp\www\jquery\test.php on line 55)
My code thus far is as follows:
$diff_results = array();
foreach($diff_date_results as $entry){
$diff_results[$entry['differential']];
}
print_r($diff_results);
I am sure it is simple, I have been screwing around with it for way too long now, any help would be wonderful!
Thanks.
$diff_results = array();
foreach($diff_date_results as $entry){
$diff_results[] = $entry['differential'];
}
//just for displaying all differential
print_r($diff_results);
Now, you can use array_sum on $diff_results.
Moreover, if you want to have sum then you can use below method too.
$diff_results = "";
foreach($diff_date_results as $entry){
$diff_results = $diff_results + $entry['differential'];
}
//$diff_results will have sum of all differential
echo $diff_results;
$diff_results = array_map($diff_date_results,
function($entry) { return $entry['differential']; });
Do it like this:
$diff_results = array();
foreach($diff_date_results as $key => $entry){
$diff_results[] .= $entry['differential']];
}
print_r($diff_results);
Thanks.
$diff_date_results = array (
0 => array ( 'differential'=> 7.7, 'date' => 20),
1 => Array ( 'differential' => 8.8, 'date' => 20 ),
2 => Array ( 'differential' => 9.8 ,'date' => 20 ),
);
$value_differential=array();
foreach( $diff_date_results as $key=>$value){
print_r($value);
$value_differential[]=$value['differential'];
}
print_r(array_sum($value_differential));
For anyone stumbling across this question as I have, the best solution in my opinion is a working version of Barmars as below:
$diff_results = array_map(function($entry)
{
return $entry['differential'];
},
$diff_date_results);
it's a more elegant, 1 line solution (which I've expand to 5 lines for readability).

Sorting a 3 dimensional array

I've got an array like this
Array
(
[0] => Array
(
[0] => Array
(
[szam] => 8
[index] => 0
)
)
[1] => Array
(
[0] => Array
(
[szam] => 1
[index] => 0
)
[1] => Array
(
[szam] => 7
[index] => 1
)
)
I thought that my last cmp will work fine
function maxSzerintCsokkeno($item1,$item2)
{
if ($item1['szam'] == $item2['szam']) return 0;
return ($item1['szam'] < $item2['szam']) ? 1 : -1;
}
with foreach
foreach ($tomb as $kulcs => $adat) usort($adat,"maxSzerintCsokkeno");
but it dosen't do anything, advise?
foreach ($tomb as $kulcs => $adat) usort($adat,"maxSzerintCsokkeno");
This only sorts the subarray array $adat. And this only exists temporarily until foreach loops over the next one. The lazy option here would be to use a reference:
foreach ($tomb as & $adat) usort($adat,"maxSzerintCsokkeno");
Notice the &. This way the modification on $adat will be applied directly in the parent array.
You're sorting a temporary variable, meaning the changes are not applied. The following should work for you:
for($i = 0, $length = count($tomb); $i < $length; $i++)
{
usort($tomb[$i], "maxSzerintCsokkeno");
}
When iterating through the foreach loop, the key and value variables ($kulcs and $adat in your code) are copies of the actual values in the array. Like Tim Cooper said, you are actually sorting a copy of the original value.
You can also pass the value by reference in your foreach loop. This means that you will be modifying the original value:
foreach ($tomb as $kulcs => &$adat) usort($adat,"maxSzerintCsokkeno");

checking to see if a vaule is in a particular key of an array

I'm new to working with arrays so I need some help. With getting just one vaule from an array. I have an original array that looks like this:
$array1= Array(
[0] => 1_31
[1] => 1_65
[2] => 29_885...)
What I'm trying to do is seach for and return just the value after the underscore. I've figured out how to get that data into a second array and return the vaules as a new array.
foreach($array1 as $key => $value){
$id = explode('_',$value);
}
which gives me:
Array ( [0] => 1 [1] => 31 )
Array ( [0] => 1 [1] => 65 )
Array ( [0] => 29 [1] => 885 )
I can also get a list of the id's or part after the underscore by using $id[1] I'm just not sure if this is the best way and if it is how to do a search. I've tried using in_array() but that searches the whole array and I couldn't make it just search one key of the array.
Any help would be great.
If the part after underscore is unique, make it a key for new array:
$newArray = array();
foreach($array1 as $key => $value){
list($v,$k) = explode('_',$value);
$newArray[$k] = $v;
}
So you can check for key existence with isset($newArray[$mykey]), which will be more efficient.
You can use preg_grep() to grep an array:
$array1= array("1_31", "1_65", "29_885");
$num = 65;
print_r(preg_grep("/^\d+_$num$/", $array1));
Outputs:
Array
(
[1] => 1_65
)
See http://ideone.com/3Fgr8
I would say you're doing it just about as well as anyone else would.
EDIT
Alternate method:
$array1 = array_map(create_function('$a','$_ = explode("_",$a); return $_[1];'),$array1);
echo in_array(3,$array1) ? "yes" : "no"; // 3 being the example
I would have to agree. If you wish to see is a value exists in an array however just use the 'array_key_exists' function, if it returns true use the value for whatever.

Categories