Foreach with Multidimensional Array


#1

I have code that gets a text file, reads it and finds all matches for scores > 60.00. $file returns this array:

[code]


Array
(
[0] => Array
(
[points] => 62.85
[name] => Joe Smith - Jane Smith
[entirety] => 6 62.85 90.50 A 1 2 1.97(OA) Joe Smith - Jane Smith
)
[1] => Array
    (
        [points] => 71.43
        [name] =>  Harold Cain - Margie McKenney
        [entirety] =>   8   71.43  102.86  B   1     1           1     1          2.63(OA) Harold Cain - Margie McKenney
    )

[2] => Array
    (
        [points] => 62.70
        [name] =>  Bill Johnson - Bailey Chase
        [entirety] =>   4   62.70   90.29  A   2                 3                1.48(OA) Bill Johnson - Bailey Chase
    )

)

[/code]

I have the following loop which is supposed to get each ‘entirety’ line and turn each line red and then output the entire file ($arr) again. My problem is that it’s only turning the last line ( for Bill Johnson - Bailey Chase) red instead of all three in the array above. What am I doing wrong? Thanks in advance!

[php]foreach($file as $item ) {
$myline = $item[‘entirety’];
$newline = “” . $myline . ‘’;
$newphrase = str_replace($myline, $newline, $arr);

}

echo ‘

’ . implode($newphrase) . ‘
’;[/php]

#2

[php]
$newphrase = str_replace($myline, $newline, $arr);
[/php]
needs to be changed to…
[php]
$newphrase .= str_replace($myline, $newline, $arr);
[/php]
Note the concatenation operator in the revised version. You were accidentally over-writing the var in every iteration of the loop instead of appending to it. An alternative to the shorthand method above is this:
[php]
$newphrase = $newphrase . str_replace($myline, $newline, $arr);
[/php]


#3

Thanks Rob! So when I changed that line I got an undefined variable error for $newphrase. So I added:
[php]$newphrase = ‘’;
$newphrase .= str_replace($myline, $newline, $arr);[/php]

Now I’m getting Notice: Array to string conversion on the $newphrase line and Warning: implode(): Argument must be an array on the echo line:

[php]echo ‘

’ . implode($newphrase) . ‘
’;[/php]

$arr is the array of the original file while $file is the array of just the matches. If I implode $arr so that it’s a string the Array to string error goes away and the code works but still only turns only one match red instead of all.

Do you think the problem is with $myline = $item[‘entirety’];? If I echo $item[‘entirety’] instead of assigning it to a var it does give me all matches:

6 62.85 90.50 A 1 2 1.97(OA) Joe Smith - Jane Smith 8 71.43 102.86 B 1 1 1 1 2.63(OA) Harold Cain - Margie McKenney 4 62.70 90.29 A 2 3 1.48(OA) Bill Johnson - Bailey Chase

This is great, except I need it to replace each of those lines to surround it in a span tag and then echo the entire file again with the changes. This is also the first time that I’ve worked with foreach and arrays in this capacity so really struggling. Thanks again!


#4

I think below is what you need. Don’t pre-process the file into an array with only scores > 60. Use the if-statement in the loop and conditionally make the change. HTML markup should have double-quotes for attributes so I’ve modified that section to reflect. When you wrap a php string in double-quotes on the outside, a concept called interpolation is done such that the inner variables in the string get replaced (i.e. the element reference). I’d suggest improve your naming conventions. It helps you code better (see second version below).
[php]
foreach($arr as $item ){
if($item[‘points’]>60){
$item[‘entirety’] = “<span style=“color: red;”>{$item[‘entirety’]}”;
}
}
echo ‘

’ . implode($arr) . ‘
’;
[/php]

[php]
foreach($arrOfArrFile as $arrItem ){
if($arrItem[‘points’]>60){
$beforeChange = $arrItem[‘entirety’];
$afterChange = “<span style=“color: red;”>$beforeChange”;
$arrItem[‘entirety’] = $afterChange;
}
}
echo ‘

’ . implode($arrOfArrFile) . ‘
’;
[/php]
And in the second version, I used steps to make it easier to follow the logic. Note that braces { and } are not needed to wrap the var $beforeChange in the revised string interpolation. Braces are needed in the first version so php can parse what is intended.

#5

Hi Rob - thanks again for your quick reply - I really appreciate it! So, the last solution didn’t work either. What I’m trying to do is take a file (2918022.htm) and search the PCT column for scores > 60. Typically the htm file looks like this (but it can be different sometimes):

[code]

Thursday Afternoon Pairs Thursday Aft Session February 22, 2018
Scores after 8 rounds Average: 72.0 Section A North-South
Pair Pct Score Section Rank Overall Rank MPs
A B C A B C
6 62.85 90.50 A 1 2 1.97(OA) Jane Smith - Bob Stanley
4 55.56 80.00 A 2 5 0.83(OA) Duane Jones - Karen Jones
2 54.51 78.50 C 3 1 1 3 2 0.77(OC) Ann Sinclair - Carol Heller
5 46.88 67.50 B 2 4 0.51(OB) Jacqueline Kirby - Jane Hope
1 45.83 66.00 C 3 0.57(OC) Chris Bruce - David Tanner
3 42.71 61.50 A Kimberly Griffin - Judy Manus
7 41.67 60.00 C John Ramsey - Sue Martinez
Thursday Afternoon Pairs Thursday Aft Session February 22, 2018
Scores after 8 rounds Average: 72.0 Section A East-West
Pair Pct Score Section Rank Overall Rank MPs
A B C A B C
8 71.43 102.86 B 1 1 1 1 2.63(OA) Ray McDonough - Jackie Bailey
4 62.70 90.29 A 2 3 1.48(OA) Bill Ready - Peggy McBride

3 59.52 85.71 C 3 2 1 4 2 1 1.11(OA) George Harrison - Rudy Marquez
6 53.17 76.57 A John Burtson - Joy Kenny
7 46.03 66.29 A Fred Douglas - Margie Hennley
1 38.89 56.00 C 2 0.22(SC) Herbert Dorf - Lawrence Hoover
2 36.51 52.57 C Jean Stein - Minnie Brown
5 31.74 45.71 C Marlene Williams - Albert Hayes

[/code]

Once there is a match, get each entire line (i.e. 6 62.85 90.50 A 1 2 1.97(OA) Jane Smith - Bob Stanley), turn it red, and write it back into the original file and echo the new file on screen. Again, typically the file is only text and very small in size.

So, my entire code looks like this:

[php]
#get file
$unitfile = $_SERVER[‘DOCUMENT_ROOT’] . $path;
#if file exists
if($unitfile){

$max = 60;

$arr = array_filter(file($unitfile,FILE_SKIP_EMPTY_LINES),function($v){
return (!empty(trim($v)));
});

$file = array_values(array_filter(array_map(function($v) use ($max){

preg_match_all('/[0-9]{1,3}\.[0-9]{1,2}/',$v,$match);

$match  =   (!empty($match[0]) && count($match[0]) == 3)? $match[0] : false;

if(empty($match))
    return false;

if($match[0] < $max)
    return false;

preg_match('/(.*) - (.*)/',$v, $wholelinescore);

return [
	'entirety' => $wholelinescore[0]
];

},$arr)));

foreach($file as $item) {
$beforeChange = $item[‘entirety’];
$afterChange = “” . $beforeChange . ‘’;
$newscoresheet = str_replace($beforeChange, $afterChange, $arr);

}
echo ‘

’ . implode($newscoresheet) . ‘
’;
}
[/php]

So the code above works without errors except it only turns the last match red instead of all matches red (in the file above there are 3 matches).

I think the error is in my loop - particularly with assigning $item[‘entirety’] to a var.

if echo $item['entirety]; prints out all matches then why does $beforeChange = $item[‘entirety’]; or event $beforeChange .= $item[‘entirety’]; get all matches?

BTW, I did take your advice and changed my naming conventions - thanks! :smiley:


#6

I tried to take a look at the rest of your code but it just seems to be too busy and convoluted for me to help you out any further. My initial goal was to try to help you with your multi-dimensional array struggles (per your posted subject line), but the scope of this problem has grown a great deal. You said the format of the file you must process changes (and cannot be known with certainty). which is really crazy for me to try to come back with something that works for you. I looked at the sample file in your post and I don’t even see the word “entirety” in it–but perhaps I’m missing something–but all of the regular expressions tests and filtering you have. I get regex, but I think you might (since the files are not coming in consistent, break the file lines into an array and screen the lies based on some string comparisons. I think you should start fresh, think it over, and come up with a simpler, easier to follow approach for yourself. Make sure you understand all of the required input and output values of all of the php functions you are using in your code–you very well could be having a problem because of some incorrect assumptions of how they work and what they return. Sorry I don’t have the time to wrap up this problem for you–good luck!


#7

I forgot to say that I did see this simple problem re-introduced into your code. You are again overwriting instead of appending:
$newscoresheet = str_replace($beforeChange, $afterChange, $arr);
corrected appending version:
$newscoresheet = $newscoresheet . str_replace($beforeChange, $afterChange, $arr);
or
$newscoresheet .= str_replace($beforeChange, $afterChange, $arr);


#8

No problem - thanks for all your time! I think I will start over. Yes, forgot to add the corrected scoresheet line in my post.


#9

What is the actual file you are parsing? HTML, XML, txt? That can make things easier or more complicated.