Jump to content

A faster way to do "search and replace"?


lfernando

Recommended Posts

Hi everyone!! I just started learning PHP two weeks ago and I hope someone can help me!!

I need to do a find and replace on a string, and each replace needs to have an unique id, and if that unique id exists in a table then return the value on the table. Make sense?

 

So like "find all the Xs in the string, replace with "X1, X2, X3...", then if "X3' exists on TableB, return value "X3 is on the table and has a value of Y3".

 

I actually got this to work already but it takes a long time to do it so I'm hoping someone could give me some advice on how to make it more EFFICIENT:

 


// PART ONE, find all "X" and replace with unique_id

for ($count = 1; $count <= strlen($string); $count++) // do this loop as many times as there are characters in $string
{
$unique_id = "replacement_" . $count; // give each replacement an unique id (replacement_1, replacement_2, replacement_3, etc..)
$string = preg_replace("X", $unique_id, $string , 1); // find X and replace it with the $unique_id in $string, and only do this ONCE
} 
$count_replacements = substr_count($string,"replacement_"); // count how many replacements occured in total


// PART TWO, find all unique_ids in tableB and echo the unique_id_value

for ($count = 1; $count <= $count_replacements; $count++) // do this loop as many times as there were replacements
{
$unique_id  = "replacement_" . $count; // set the unique_id of each replacement


$show_tableB = mysqli_query($link, 'SELECT * FROM tableB');      // select  the unique_ids and the unique_id_values in TableB
while ($row = mysqli_fetch_array($show_tableB)) { $tableBs[] = array('unique_id' => $row['unique_id'], 'unique_id_value' => $row['unique_id_value']);  }    

foreach($tableBs as $tableB): // for each entry in TableB, if the unique_id in TableB matches the unique_id of the replacement, return the unique_id_value
if ($tableB['unique_id'] == $unique_id) 
{ echo $unique_id . " is on TableB and it has a value of ". $tableB['unique_id_value'] }
endforeach;

}

 

The problem with this is: its not very efficient.

If $string has 500 charachters, it does the "PART ONE" 500 times. Then, say it found 300 Xs, it does "PART TWO" 300 more times. And every time it does "PART TWO", it checks all entries in TableB (which could be 200 or more).

 

So, that's it. Anyone has a better idea of how to do this??

 

Thanks!!!!

Link to comment
Share on other sites

Get the ID # in a variable.  Get the value in another variable (via the database) and then

run an str_replace on the string. It's the fastest method for simple find/replace logic.

So basically take the ID and hit the database to get the value.

Have the id as

$find_id

$replace_value (holding the DB value you wanted to replace the ID with).

Then run an str_replace.  Only use regex if you have an advanced pattern you have to match with.

Link to comment
Share on other sites

Well you have a significant flaw in the logic. You have a loop that runs for each character in the string. Then inside the loop you use preg_replace(). There is absolutely no correlation between the loop and preg_replace(). On the first iteration of the loop preg_replace() will replace the first instance of the search string - regardless if it is at the first character position or not. So, if you have a 200 character string with 5 "x" characters, all the replacements are done after the 5th iteration of the loop - but the code will run the loop 195 more times!

 

Secondly - and more importantly - you are running queries in a loop. This is a HUGE waste of resources. Never, ever run queries in a loop. Query the data you need and process the records in PHP. Besides that loop has no purpose since you are running the same query every time without any where clause.

 

This could be made much more efficient if you separated the string and the ID in the database. But, this shoudl work for what you have

//Define search and replacement strings
$searchStr  = "X"
$replaceStr = "replacement_":

//Query all possible replacements in table and put into array
$query = "SELECT `unique_id`, `unique_id_value` FROM `tableB` WHERE `unique_id` LIKE '{$replaceStr}%'";
$result = mysqli_query($link, $query);
$replaceAry = array();
while ($row = mysqli_fetch_array($result))
{
    $replaceAry[$row['unique_id']] = $row['unique_id_value'];
}  

//Create loop to replace each search string ONLY WHILE the search string exists
$idCount = 0;
while(strpos($string, $searchStr)!==false)
{
    $idCount++; //Increment the ID
    $idStr = $replaceStr.$idCount;
    //If $idStr exists in the replaceAry echo comment to that effect
    if (isset($replaceAry[$idStr]))
    {
        echo "{$idStr} is on TableB and it has a value of {$idStr}<br />\n";
    }
    //Replace the search string with replacement and unique ID
    $string = preg_replace($searchStr, $idStr, $string, 1);
}

Link to comment
Share on other sites

Hi MJ,

 

First of all, thank you so much for your quick reply!!

In my real code, I wasnt actually running the query inside the loop, but it was still taking a long time.

 

This is how your code worked for me:

$searchStr  = "X";
$replaceStr = "replacement_";
$result = mysqli_query($link, 'SELECT * FROM tableB WHERE `unique_id` LIKE "{$replaceStr}%"'); //Query all possible replacements in table and put into array

while ($row = mysqli_fetch_array($result))    
  { $tableBs[] = array('unique_id' => $row['unique_id'], 'unique_id_value' => $row['unique_id_value']);     }  

$idCount = 0; //Create loop to replace each search string ONLY WHILE the search string exists

while(strpos($replaced, $searchStr)!==false)
{    
$idCount++; //Increment the ID    
$unique_id = $replaceStr.$idCount;   

foreach($tableBs as $tableB):   //If $unique_id exists in the table, echo the right value
if ($tableB['unique_id'] == $unique_id)
{
$unique_id = "The ID " . $unique_id . "was found and it has the value of". $tableB['unique_id_value'];
}
endforeach;

//Replace the search string with replacement and unique ID    
$string = preg_replace($searchStr, $idStr, $string, 1);
}

 

(with a few changes...) and it taks less than a split second!! Thank you so much!!

Now, any idea how I make it work for both X and x? (ignore case?).

 

Link to comment
Share on other sites

Ahh, I managed to figure it out myself. probably not the best way, but it works:

just used two variables:

$searchStrUpperCase = "X";

$seachStrLowerCase = "x";

 

then added OR to the while loop

while(strpos($replaced, $searchStrUpperCase)!==false OR  strpos($replaced, $searchStrLowerCase)!==false)

 

Thanks again for your help! :)

Link to comment
Share on other sites

No offense taken. It's jsut that PHP has one of the best online manuals in my opinion and it seems people do not take advantage of it. When using a new function you should always read the manual for that function to understnad the imput parameters and the possiblel output. Additionally, right after the examples for a function is a list of related functions. I can't tell you how many times I was reviewing a function that "kind of" did what I wanted but not exactly and then found exactly what I needed in the related functions section.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.