regex not working as expected when matching file names with wildcards - php
I am writing a PHP function that takes an array of file names and removes file names from the array if they do not match a set of criteria input by the user. The function iterates through the array and compares each value to a regex. The regex is formed by inserting variables from user input. If the user didn't specify a variable, regex wildcard characters are inserted in the variable's place. The file names are all very systematic, like 2020-06-N-1.txt so I know exactly how many characters to expect in the file names and from the user input. However, when I run the code, file names that don't match the regex are still in the array. Some non-matching file names are taken out, but many others are left in. Parts of my PHP code are below. Any help is appreciated.
function fileFilter() {
global $fileArray, $fileFilterPattern;
/* The loop starts at 2 and goes to count()-1 because the first 2 elements were removed
earlier with unset */
for ($j = 2; $j < count($fileArray) - 1; $j++) {
if(!(preg_match($fileFilterPattern, $fileArray[$j]))) {
unset($fileArray[$j]);
}
}
return;
}
// If user does not provide a filter value, it gets converted into wildcard symbol
if ($month == '') {
$month = '..';
}
if ($year == '') {
$year = '....';
}
if ($section == '') {
$section = '.';
}
$fileFilterPattern = "/{$year}-{$month}-{$section}-.\.txt/";
/* function only runs if user applied at least one filter */
if (!($month == '..' && $year == '....' && $section == '.')) {
fileFilter();
}
Below I have included an example of how the array contains elements that aren't matches. I obtain my output array using echo json_encode($fileArray);
My input:
month is ""
year is ""
section is "L"
Expected result:
Array contains only files that have L in the section spot (YEAR-MONTH-**SECTION**-NUMBER.txt)
Resulting array:
{"8":"2020-06-L-1.txt","9":"2020-06-L-2.txt","10":"2020-06-L-3.txt","11":"2020-06-L-4.txt","12":"2020-06-L-5.txt","15":"2020-06-N-3.txt","16":"2020-06-N-4.txt","17":"2020-06-N-5.txt","18":"2020-06-N-6.txt","19":"2020-06-O-1.txt","20":"2020-06-O-2.txt","21":"2020-06-O-3.txt","22":"2020-06-O-4.txt","23":"2020-06-S-1.txt","24":"2020-06-S-2.txt","25":"2020-06-S-3.txt"}
The problem is using unset() inside a loop. On the next iteration, the index is no longer the same as it was before you messed with the array using unset(). Sometimes, you deal with this by using array_values(), but in this case it's simpler to just build a second array that has only the values you want. The following code works. I've used array_values() just to take the string that you provided and get the indexes back to normal.
That said, since the "first 2 elements were removed
earlier with unset" you need to run array_values() on the array before you get to this part.
<?php
$str ='{"8":"2020-06-L-1.txt","9":"2020-06-L-2.txt","10":"2020-06-L-3.txt","11":"2020-06-L-4.txt","12":"2020-06-L-5.txt","15":"2020-06-N-3.txt","16":"2020-06-N-4.txt","17":"2020-06-N-5.txt","18":"2020-06-N-6.txt","19":"2020-06-O-1.txt","20":"2020-06-O-2.txt","21":"2020-06-O-3.txt","22":"2020-06-O-4.txt","23":"2020-06-S-1.txt","24":"2020-06-S-2.txt","25":"2020-06-S-3.txt"}';
$fileArray = json_decode($str, true);
$fileArray = array_values($fileArray);
echo '<p>fileArray: ';
var_dump($fileArray);
echo '</p>';
function fileFilter() {
global $fileArray, $fileFilterPattern;
$filteredArray = [];
for ($j = 0; $j < count($fileArray); $j++) {
if(preg_match($fileFilterPattern, $fileArray[$j]) === 1) {
//unset($fileArray[$j]);
array_push($filteredArray, $fileArray[$j]);
}
}
echo '<p>filteredArray: ';
var_dump($filteredArray);
echo '</p>';
//return;
}
$month =='';
$year = '';
// If user does not provide a filter value, it gets converted into wildcard symbol
if ($month == '') {
$month = '..';
}
if ($year == '') {
$year = '....';
}
if ($section == '') {
$section = '.';
}
$section = 'L';
$fileFilterPattern = "#{$year}-{$month}-{$section}-.\.txt#";
echo '<p>fileFilterPattern: ';
var_dump($fileFilterPattern);
echo '</p>';
/* function only runs if user applied at least one filter */
if (!($month == '..' && $year == '....' && $section == '.')) {
fileFilter();
}
?>
The main problem is that the count decreases each time you unset, so you should define the count once. Assuming the -1 and $j = 2 are correct for your scenario:
$count = count($fileArray) - 1;
for ($j = 2; $j < $count; $j++) {
if(!(preg_match($fileFilterPattern, $fileArray[$j]))) {
unset($fileArray[$j]);
}
}
There are others ways where you don't have to assume and then keep track of the keys:
foreach($fileArray as $k => $v) {
if(!preg_match($fileFilterPattern, $v)) {
unset($fileArray[$k]);
}
}
I would get rid of your fileFilter function and use this handy function instead, which will return all items that match the pattern:
$fileArray = preg_grep($fileFilterPattern, $fileArray);
Related
looping through txt file to use specific part of a string
I am new to Php and can't seem to figure this out no matter how much I've googled. So I've opened the txt file (which consists of multiple lines of this type of string unique Identifier IMEI in bold: Rx:00:39:54 06/09/2015:+RESP:GTEPS,210101,863286020022449,,8296,01,1,3,0.0,0,1031.1,29.367950,-30.799161,20150906003710,,,,,,2857.9,20150906003710,8038$) There are different strings with different IMEIs but i only want to use a specific one. My question is, how do I extract/only use the string with the same Unique identifier and then loop through those to use in another function? My function has different cases and each case has different calculations, so I'll need to loop through the txt file (with e.g. 863286020022449 as Identifier, ignoring other identifiers/IMEIs) in order to use the string in my function as below: This is my starter function: function GetParam($unknownFunction, $numberCommas) { $returnString = ""; $foundSting = 0; $numberFound = 0; $len = strlen($unknownFunction); for ($i = 0; $i < $len; ++$i) { if ($Rawline[$i] == ",") { ++$numberFound; if ($numberFound > $numberCommas) break; if ($numberFound == $numberCommas) $foundSting = 1; } else if ($foundSting == 1) { $returnString .= $unknownFunction[$i]; } } return $returnString; echo $returnString; } $i = strpos($unknownFunction, ":GT"); $p = substr($unknownFunction, $i+3,3); $Protocol = GetParam($unknownFunction, 1); //this switch reads the differences in the message types (e.g. HBD- in this case is a heartbeat message type and would thus have a different amount of commas in the string and has different definitions of the characters within the commas) switch ($p) { case 'HBD': //+ACK:GTHBD,220100,135790246811220,,20100214093254,11F0$ //This is an example of an HBD message $result2["Type"] = 'Heart beat'; $IMEI = GetParam($unknownFunction, 2); $mDate = GetParam($unknownFunction, 4); $mDate = substr($mDate,0,4).'-'.substr($mDate,4,2).'- '.substr($mDate,6,2).' '.substr($mDate,8,2).':'.substr($mDate,10,2).':'.substr($mDate,12,2); break; This is the biggest problem I am facing at the moment and when I print the different lines, it indicates the correct IMEI but it does not loop through the whole file to use each string that belongs to that IMEI. Your assistance would be greatly appreciated. Thank you so much. Example of input file: Rx:00:00:00 28/02/2018:+RESP:GTFRI,3C0103,862045030241360,,14067,11,1,1,29.7,320,151.1,30.949307,-29.819685,20180227235959,0655,0001,013A,87B6,00,35484.1,01500:51:31,,,100,220101,,,,20180228000000,3461$ Rx:00:00:01 28/02/2018:+RESP:GTERI,380201,869606020047340,gv65,00000002,14076,10,1,1,119.0,119,24.3,18.668516,-34.016808,20180227235955,0655,0001,00F7,2DC9,00,98912.0,02235:20:25,0,100,220101,0,0,20180227235958,FF20$ Rx:00:00:03 28/02/2018:+RESP:GTERI,380201,869606020162990,,00000002,12912,10,1,1,0.0,230,1127.3,30.846671,-27.674206,20180227235956,0655,0001,013E,88B0,00,106651.1,03546:44:42,0,100,210101,0,0,20180227235959,6190$ Rx:00:00:03 28/02/2018:+ACK:GTHBD,450102,865084030005340,gb100,20180228000003,CC61$ Rx:00:00:03 28/02/2018:+RESP:GTERI,380201,869606020115980,,00000002,13640,10,1,1,12.1,353,1663.1,28.580726,-28.162208,20180227235957,,,,,,37599.6,02422:07:24,0,100,220101,0,0,20180228000000,1937$ Rx:00:00:04 28/02/2018:+RESP:GTERI,380502,869606020276840,gv65,00000002,12723,10,1,1,0.0,106,1232.8,22.878013,-27.951762,20180227235952,0655,0001,0204,63C5,00,13808.9,00778:32:20,0,100,210100,0,0,20180228000002,2C50$ Rx:00:00:04 28/02/2018:+RESP:GTERI,380502,869606020274530,gv65,00000002,12683,10,1,1,0.0,91,1213.7,24.863444,-28.174319,20180227235956,0655,0001,0203,69F1,00,9753.2,00673:49:21,0,100,210100,0,0,20180228000003,8AC7$ Rx:00:00:05 28/02/2018:+ACK:GTHBD,380201,863286023083810,,20180228000003,0D87$ Rx:00:00:06 28/02/2018:+RESP:GTFRI,3C0103,862045030241360,,14086,10,1,1,34.0,327,152.0,30.949152,-29.819501,20180228000002,0655,0001,013A,87B6,00,35484.1,01500:51:36,,,100,220101,,,,20180228000005,3462$ Rx:00:00:06 28/02/2018:+ACK:GTHBD,060228,862894021626380,,20180228000007,F9A5$ Rx:00:00:07 28/02/2018:+RESP:GTERI,380201,869606020019430,,00000002,12653,10,1,1,0.0,219,1338.7,26.882063,-28.138099,20180228000002,,,,,,86473.7,05645:48:34,0,93,210101,0,0,20180228000003,0FA5$ Rx:00:00:09 28/02/2018:+ACK:GTHBD,380502,869606020233940,gv65,20180228000008,7416$ Rx:00:00:10 28/02/2018:+RESP:GTAIS,380201,869606020171710,,11,11,1,1,0.0,95,281.2,30.855164,-29.896575,20180228000009,0655,0001,0156,9A9F,00,156073.7,20180228000008,F9A4$ Each GT message means something which is why i need to extract only one specific IMEI and use the result in my function as a breakdown of what every set of numbers between the commas actually mean. The end result needs to be populated in an excel spreadsheet but that's a different issue.
Nested foreach, keeping tracking of the IMEIs you've already gone through. Or something like this. <?php $filename = 'info.txt'; $contents = file($filename); foreach ($contents as $line) { $doneAlreadyArray = array(); $IMEI = GetParam($line, 2); foreach ($contents as $IMEIline){ $thisIMEI = GetParam($IMEIline,2); //check if already done the IMEI previously if (!in_array($thisIMEI, $doneAlreadyArray)){ //matching IMEIs? if ($thisIMEI == $IMEI){ //run new function with entire $IMEIline new_function($IMEIline); } } } //add IMEI to doneAlreadyArray array_push($doneAlreadyArray,$IMEI); } ?>
If I've understood your question right and you want to extract the string(line) with the same Unique identifier, this may be useful for your needs as a strating point. The example is very basic, and use data from your question: <?php // Read the file. $filename = 'input.txt'; $file = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // Each item of $output will contain an array of lines: $output = array(); foreach ($file as $row) { $a = explode(',', $row); $imei = $a[2]; if (!array_key_exists($imei, $output)) { $output[$imei] = array(); } $output[$imei][] = $row; } // Then do what you want ... foreach ($output as $key=>$value) { echo 'IMEI: '.$key.'</br>'; foreach($value as $row) { // Here you can call your functions. I just echo the row: echo $row.'</br>'; } } ?>
thank you for the feedback. Ryan Dewberry ended up helping me. The fix was simpler than I thought too :) //Unknownfunction is now $line function GetParam($line, $numberCommas) { $returnString = ""; $foundSting = 0; $numberFound = 0; $len = strlen($line); for ($i = 0; $i < $len; ++$i) { if ($line[$i] == ",") { ++$numberFound; if ($numberFound > $numberCommas) break; if ($numberFound == $numberCommas) $foundSting = 1; } else if ($foundSting == 1) { $returnString .= $line[$i]; } } return $returnString; // print $returnString; } //this is new - makes sure I use the correct IMEI $contents = file($fileName); foreach ($contents as $line){ $haveData = 0; $IMEI = GetParam($line, 2); if ($IMEI == $gprsid){ $i = strpos($line, ":GT"); $p = substr($line, $i+3,3); $Protocol = GetParam($line, 1); //this is the part I struggled with as well - This is an array of all of my //calculation //results and in printing it out I can see that everything is working $superResult = array(); array_push($superResult,$result2); print_r($superResult); } } Much appreciated. Thank you!
How to continuously push user input data into $_SESSION array and then retrieve it?
I am trying to get my head around the way PHP sessions work. I am simply trying a hangman game where the first player inputs a secret word, a second player then starts to guess one letter at a time. Let's says that the secret word is cat, player two tries, c then a then s. I would like the final output to be c a _. <?php session_start(); global $word; global $guess; global $hangman; if (isset($_POST['player1'], $_POST['word'])) { $_SESSION['word'] = $_POST['word']; $word = $_SESSION['word']; } if (isset($_POST['player2'], $_POST['guess'])) { $_SESSION['guess'] = $_POST['guess']; $guess = $_SESSION['guess']; } $counter = 0; $word = strtolower($_SESSION['word']); $guess = strtolower($_SESSION['guess']); echo $word . "<br>"; $found = []; $counter = 0; for ($i = 0; $i < strlen($word); $i++) { if ($counter < strlen($word)) { if (strpos($word[$i], $guess) !== false) { $found[] = $guess; $counter++; } else { $found[] = " _ "; } } } print_r($found); Instead of printing out all the contents the found array, I am only getting one single letter to print every time. However, I would like to see the full concatenated string as I've mentioned above. Here is what the output looks like:
How to continuously push user input data into $_SESSION array and then retrieve it? An easy way to do that is by binding a variable with an element in the $_SESSION array. This is a useful trick that you won't find in the manual. A simple example: $foo =& $_SESSION['foo']; That assignment will bind $foo and $_SESSION['foo'] to the same value, so every update to $foo is also an update to $_SESSION['foo']. Here is an example usage in the style of your hangman game: <?php session_start(); $word =& $_SESSION['word']; //bind $word with $_SESSION['word'] $found =& $_SESSION['found']; //bind $found with $_SESSION['found'] if (isset($_REQUEST['word'])) { $word = str_split($_REQUEST['word']); $found = array_fill(0, count($word), '_'); } if (isset($_REQUEST['guess'], $word, $found)) { $guess = array_fill(0, count($word), $_REQUEST['guess']); $found = array_replace($found, array_intersect($word, $guess)); } echo join(' ', $found); With the binding, the values of $word and $found will be saved as a part of the session data, without the need to do $_SESSION['word'] = $word; and $_SESSION['found'] = $found; anywhere in the script. Note that I use $_REQUEST instead of $_POST to make it easier to test with a browser. Modify as desired.
Make the $found as a string variable.Instead of pushing in $found[] ,concatenate $guess Like $found .= $guess;
You should save what was already found between requests, since now you are just searching the $_SESSION['word'] for the char in the last request. if ( isset($_POST['player1']) && !empty($_POST['word']) ) { $_SESSION['word'] = str_split( $_POST['word'] ); // ceate empty array for storing the already found chars $_SESSION['found'] = str_split( str_repeat( " ", strlen($_POST['word']) ) ); } if ( isset($_POST['player2']) && !empty($_POST['guess']) ) { array_walk( $_SESSION['word'], function( $v, $k ) { if ( $v == $_POST['guess'] ) $_SESSION['found'][$k] = $v; }); } if ( $_SESSION['word'] == $_SESSION['found'] ) echo 'Game Over'; print_r( $_SESSION['found'] );
You are overwriting your $_SESSION['guess'] with: $_SESSION['guess'] = $_POST['guess']; on every submission. I would recommend that you store your posted guesses as a subarray of letters like: $_SESSION['guesses'][] = $_POST['guess']; Then you will never overwrite earlier guesses. This will mean you will have a session array with this type of structure: $_SESSION=[ 'player1' => 'me', 'word' => 'cat', 'player2' => 'myself', 'guesses' => ['a','c'] ]; From here, you can call str_split() on $_SESSION['word'] and check for found/remaining letters using $_SESSION['guesses'] and array comparison functions. Here are some untested portions of code that may help you along... session_start(); if (!isset($_SESSION['player1'], $_SESSION['word'])) { // no stored player1 or word if (!isset($_POST['player1'], $_POST['word'])) { // no posted player1 or word // show form with player1 and word fields } else { $_SESSION=['player1'=>$_POST['player1'],'word'=>strtolower($_POST['word'])]; // store player1 and word } } elseif (!isset($_SESSION['player2'], $_SESSION['guesses'])){ // no stored player2 or guesses if (!isset($_POST['player2'], $_POST['guess'])) { // no posted player2 or guess // show form with player2 and first guess } else { $_SESSION['player2'] = $_POST['player1']; // store player2 $_SESSION['guesses'] = [strtolower($_POST['guess'])]; // store guessed character as first element of subarray } } elseif (isset($_POST['guess'])) { $_SESSION['guesses'][] = strtolower($_POST['guess']); // store guessed character } And further down script here are some pieces... $secret_letters=array_unique(str_split($_SESSION['word'])); // unique secret word letters $found_letters=array_intersect($secret_letters,$_SESSION['guesses']); // unique found letters if($secret_letters===$found_letters){ // player2 guessed all of the secret letters, set off fireworks }else{ // some useful bits of code... $not_yet_found=array_diff($secret_letters,$_SESSION['guesses']); $underscored=str_replace($not_yet_found,'_',$_SESSION['word']); // e.g. 'ca_' $space_out=implode(' ',str_split($underscored)); // e.g. 'c a _' $wrong_letters=array_diff($_SESSION['guesses'],$secret_letters); // letters guessed but not part of secret word // when count($wrong_letters) reaches your designated limit, then the guesser loses $avaliable_letters=array_diff(range('a','z'),$_SESSION['guesses']); $select="<select name=\"guess\"><option>".implode('</option><option>',$available_letters)."</option></select>"; } I should also note, there are many ways to tackle this project. You should have a look at count_chars(), it has multiple modes which you should research and consider. There will be regex methods that may be helpful, but I won't open up that can for you.
I see your problem now. you didn't save or hold the previous guess because your found[] array variable is always empty. try to save the found result in a session and change this following line of code: for ($i = 0; $i < strlen($word); $i++) { if ($counter < strlen($word)) { if (strpos($word[$i], $guess) !== false) { $found[] = $guess; $counter++; } else { $found[] = " _ "; } } } TO: $counterWord = strlen($word); for ($i = 0; $i < $counterWord ; $i++) { if (strpos($word[$i], $guess) !== false) { $found[$i] = $guess; // $i indicates what index should be changed } else { if(!isset($found[$i])){ $found[$i] = "_"; } } $_SESSION['found'] = $found; and add this line of code under the declaring of your $found array variable: $found = []; if(isset($_SESSION['found'])){ //checker if the variable is set and not empty $found = $_SESSION['found']; // getting the value of found and store it in found variable }
Removing an array from a PHP JSON object
So a bit of background information is I'm creating a web app and I have 50~ arrays that I'm currently using what I get from an API, I've created a script to find the arrays that I don't need lets call them "bad arrays" but the problem is I'm unsure how I can filter these arrays out with the method I'm using to search through them I'm searching through them with this script $tagItems = []; foreach($tags['items'] as $item) { if (!$item['snippet']['tags'] || !is_array($item['snippet']['tags'])) { continue; } foreach($item['snippet']['tags'] as $tag) { $tag = strtolower($tag); if (!isset($tagItems[$tag])) { $tagItems[$tag] = 0; } $tagItems[$tag]++; } } But let's say I didn't want it to include the 8th array and the 15th array $tags['items'][8]['snippet']['tags']; $tags['items'][15]['snippet']['tags']; I want these to be removed from the original $tags array. How can i achieve this? EDIT: This needs to be dynamic. I do not know if there are going to be 45/50 arrays that will need removing or just 2/50. the array that needs removing can be reffered to as $index I have a script which determines what array(s) need to be removed $i = 0; while ($i <= 50) { $x = 0; while ($x <= 50) { if ($tags['items'][$i]['snippet']['channelId'] == $tags['items'][$x]['snippet']['channelId']) { if ($x < $i) { break; } else { echo $x.", "; break; } } $x++; } $i++; } I'm going to edit this a little more to provide some extra information that may be useful. My overall goal is to use the YouTube API to remove all but the first array of tags where the channel id appears multiple times. I'm using a script which finds all the array numbers that dont need to be removed an URL.
You can check for the array key $tagItems = []; $toRemove = array(8,15); foreach($tags['items'] as $key => $item) { if(in_array($key,$toRemove)){ continue; } if (!$item['snippet']['tags'] || !is_array($item['snippet']['tags'])) { continue; } foreach($item['snippet']['tags'] as $tag) { $tag = strtolower($tag); if (!isset($tagItems[$tag])) { $tagItems[$tag] = 0; } $tagItems[$tag]++; } }
Ensure order in for loop involving json_decode()
I'm using json_decode to parse JSON files. In a for loop, I attempt to capture specific cases in the JSON in which one element or another exist. I've implemented a function that seems to fit my needs, but I find that I need to use two for loops to get it to catch both of my cases. I would rather use a single loop, if that's possible, but I'm stuck on how to get both cases caught in a single pass. Here's a mockup of what I would like the result to look like: <?php function extract($thisfile){ $test = implode("", file($thisfile)); $obj = json_decode($test, true); for ($i = 0; $i <= sizeof($obj['patcher']['boxes']); $i ++) { //this is sometimes found 2nd if ($obj['patcher']['boxes'][$i]['box']['name'] == "mystring1") { } //this is sometimes found 1st if ($obj['patcher']['boxes'][$i]['box']['name'] == "mystring2") { } } } ?> Can anyone tell me how I could catch both cases outlined above within a single iteration? I clearly could not do something like if ($obj['patcher']['boxes'][$i]['box']['name'] == "string1" && $obj['patcher']['boxes'][$i]['box']['name'] == "string2") {} ...because that condition would never be met.
Generally what I do when I have raw data that is in an order that isn't ideal to work with is to run a first loop pass to generate a a list of indexes for me to pass through a second time. So a quick example from your code: <?php function extract($thisfile){ $test = implode("", file($thisfile)); $obj = json_decode($test, true); $index_mystring2 = array(); //Your list of indexes for the second condition //1st loop. $box_name; for ($i = 0; $i <= sizeof($obj['patcher']['boxes']); $i ++) { $box_name = $obj['patcher']['boxes'][$i]['box']['name']; if ( $box_name == "mystring1") { //Do your code here for condition 1 } if ($box_name == "mystring2") { //We push the index onto an array for a later loop. array_push($index_mystring2, $i); } } //2nd loop for($j=0; $j<=sizeof($index_mystring2); $j++) { //Your code here. do note that $obj['patcher']['boxes'][$j] // will refer you to the data in your decoded json tree } } ?> Granted you can do this in more generic ways so it's cleaner (ie, generate both the first and second conditions into indexes) but i think you get the idea :)
I found that something like what #Jon had mentioned is probably the best way to attack this problem, for me at least: <?php function extract($thisfile){ $test = implode("", file($thisfile)); $obj = json_decode($test, true); $found1 = $found2 = false; for ($i = 0; $i <= sizeof($obj['patcher']['boxes']); $i ++) { //this is sometimes found 2nd if ($obj['patcher']['boxes'][$i]['box']['name'] == "mystring1") { $found1 = true; } //this is sometimes found 1st if ($obj['patcher']['boxes'][$i]['box']['name'] == "mystring2") { $found2 = true; } if ($found1 && $found2){ break; } } } ?>
PHP string sort by letter range can't execute single character comparison
I'm working on outputing a list of companies in a foreach statement. To compare the first letters of each company I'm substinging the first character of each. These need to be sent through an if comparitor operation to see if it's the first occurance of each range of inital character. The var_dump shows that the srt_cmp has found the values intended. When I use the value in a if comparison for many combination, the if statement will not execute. <?php $stringCompanyListing = '<!-- beginning of business listing -->'."\n"; $countCompanies=0; $haveStrungAD = ""; $haveStrungEI = ""; $haveStrungJO = ""; $haveStrungPU = ""; $haveStrungVZ = ""; foreach ($files as $file){ $company = new SimpleXMLElement($file, 0, true); $COMPANYKEY[$countCompanies] = basename($file, '.xml'); if ($countCompanies >= 1){ $currentCompany = substr($COMPANYKEY[$countCompanies],0, 1); $previousCompany = substr(($COMPANYKEY[($countCompanies-1)]),0, 1); $checkForNavigation = strcmp($previousCompany, $currentCompany); // var_dump at this point show intended values such as "A" and "-1" if ($haveStrungAD == ""){ if ($currentCompany == range("A", "D")){ if ($checkForNavigation <= -1){ $stringCompanyListing .= ' <div class="categoryHeading"><a name="atod"></a>A-D</div>'; $haveStrungAD = "done"; } } } if ($haveStrungEI == ""){ if ($currentCompany == range("E", "I")){ if ($checkForNavigation <= -1){ $stringCompanyListing .= ' <div class="categoryHeading"><a name="etoi"></a>E-I</div>'; $haveStrungEI = "done"; } } } // more if comparisons omitted } $countCompanies++; }
Since you have all the company names in an array ($COMPANYKEY), couldn't you just sort the array using either usort () or uasort() (depending on if you need the keys to remain attached to the values). Then loop through the array and assign companies to the appropriate array. For example, uasort($COMPANYKEY, function ($a, $b) { return $a < $b; }); foreach ($COMPANYKEY AS $comp) { $char = substr($comp, 0, 1); //get first letter if ($char <= 'd') $atod[] = $comp; elseif ($char > 'd' && $char <= 'm') $etom[] = $comp; } You can write additional conditions to load into the company into additional arrays, or you can use a switch statement on $char and write a bunch of cases. Either way, this should load each. Additionally, if you are using your code, you need to not use == operator and use the inarray() function. range returns an array of values, so you need to check if your value is that array, not is equal to an array. Hope this helps.