Printable Version of Topic

Click here to view this topic in its original format

HTMLHelp Forums _ Server-side Scripting _ Exact Match

Posted by: Dag Apr 8 2020, 06:27 AM

I need to find and replace strings inside the text. In this case, text is in the array format. I don't want to replace parts of the string if full string do not match. Samples:

CODE

$find = array('Dominican Republic','Netherlands Antilles','Netherlands','Republic');
$replace = array('Доминиканская Республика','Нидерландские Антильские острова','Нидерланды','Република');
$text = array('Netherlands','Caribbean Netherlands','Republic','Dominican Republic','Netherlands Antilles','My Personal Republic');
$textNew = str_replace($find,$replace,$text);

Result is
CODE

Array
(
    [0] => Нидерланды
    [1] => Caribbean Нидерланды
    [2] => Република
    [3] => Доминиканская Республика
    [4] => Нидерландские Антильские острова
    [5] => My Personal Република
)

Walking through string by string... here is one string only:
CODE

$text = array('Caribbean Netherlands');

Result is
CODE

Array
(
    [0] => Caribbean Нидерланды
)

Regexp "/b" didn't help.
Any ides about this? Is it well known issue and is it very simple to be solved?
Thanks in advance.

Posted by: Christian J Apr 8 2020, 04:38 PM

QUOTE(Dag @ Apr 8 2020, 01:27 PM) *

I don't want to replace parts of the string if full string do not match.

I suppose that's what str_replace() is meant to do. Usually $text is a string, but even if it's an array the function just checks the string value of each $text array item.

QUOTE
Any ides about this? Is it well known issue and is it very simple to be solved?

I was thinking maybe you could do this:

CODE
$find = array('foo', 'bar');
$replace = array('FOO', 'BAR');
$text = array('foo', 'bar', 'foobar');

for($i=0; $i<count($text); $i++)
{
    for($j=0; $j<count($find); $j++)
    {
        if($text[$i]==$find[$j])
        {
            $textNew[$i]=$replace[$j];
        }
        else
        {
            $textNew[$i]=$text[$i];
        }
    }
}

echo '<pre>';
print_r($textNew);
echo '</pre>';

but for some reason it returns this:

CODE
Array
(
    [0] => foo
    [1] => BAR
    [2] => foobar
)

[1] and [2] are what I expected, but shouldn't [0] be uppercase FOO? Haven't done any PHP in a long time. unsure.gif


Posted by: Dag Apr 9 2020, 05:00 AM

Hi Chris.

See, text is always string. I just take it from array, phrase by phrase (element by element). So, I have very short string 20-40 characters and replacing it (lat) with another (cyr). My lat string has no boundaries, I can't say "Take this line from here to here"... what I need is ellementary: take all this string and replace with this one. If you haven't cyr translation, keep it as is, don't mess it...

It must be solvable with some preg_replace(match) trick... I remember that I saw someshere attitute... as do it but in lazy mode... less aggressive...

Doing all of that with character-one-by-one would be very slow... too many lines... My sample is very clear I think...

When I find it, I'll post the solution here...

Posted by: Christian J Apr 9 2020, 06:10 AM

QUOTE(Christian J @ Apr 8 2020, 11:38 PM) *

but for some reason it returns this:

CODE
Array
(
    [0] => foo
    [1] => BAR
    [2] => foobar
)

[1] and [2] are what I expected, but shouldn't [0] be uppercase FOO? Haven't done any PHP in a long time. unsure.gif

I think I found the bug in my script above. The very first $j iteration works correct:

CODE
if($text[0]==$find[0]) // foo==foo

and does change "foo" to "FOO" in $textNew[0]. But in the next $j iteration:

CODE
if($text[0]==$find[1]) // foo!=bar

the IF compares "foo" with "bar", and because that's FALSE, $textNew[0] is changed again (this time by the ELSE condition) from "FOO" to the "foo" value of $text[0]).

This version might work better:

CODE
$find = array('foo', 'bar');
$replace = array('FOO', 'BAR');
$text = array('foo', 'bar', 'foobar');

$textNew=$text; // I first copy the whole array, only changing values later (if needed)

for($i=0; $i<count($text); $i++)
{
    for($j=0; $j<count($find); $j++)
    {
        if($text[$i]==$find[$j])
        {
            $textNew[$i]=$replace[$j]; // change array values only when needed (no need for ELSE condition)
        }
    }
}

echo '<pre>';
print_r($textNew);
echo '</pre>';



Posted by: Dag Apr 9 2020, 11:18 AM


Will you retry with my samples?

QUOTE(Christian J @ Apr 9 2020, 03:10 PM) *

QUOTE(Christian J @ Apr 8 2020, 11:38 PM) *

but for some reason it returns this:

CODE
Array
(
    [0] => foo
    [1] => BAR
    [2] => foobar
)

[1] and [2] are what I expected, but shouldn't [0] be uppercase FOO? Haven't done any PHP in a long time. unsure.gif

I think I found the bug in my script above. The very first $j iteration works correct:

CODE
if($text[0]==$find[0]) // foo==foo

and does change "foo" to "FOO" in $textNew[0]. But in the next $j iteration:

CODE
if($text[0]==$find[1]) // foo!=bar

the IF compares "foo" with "bar", and because that's FALSE, $textNew[0] is changed again (this time by the ELSE condition) from "FOO" to the "foo" value of $text[0]).

This version might work better:

CODE
$find = array('foo', 'bar');
$replace = array('FOO', 'BAR');
$text = array('foo', 'bar', 'foobar');

$textNew=$text; // I first copy the whole array, only changing values later (if needed)

for($i=0; $i<count($text); $i++)
{
    for($j=0; $j<count($find); $j++)
    {
        if($text[$i]==$find[$j])
        {
            $textNew[$i]=$replace[$j]; // change array values only when needed (no need for ELSE condition)
        }
    }
}

echo '<pre>';
print_r($textNew);
echo '</pre>';



Posted by: Christian J Apr 9 2020, 01:31 PM

QUOTE(Dag @ Apr 9 2020, 06:18 PM) *

Will you retry with my samples?

Then I get:

CODE
Array
(
    [0] => Нидерланды
    [1] => Caribbean Netherlands
    [2] => Република
    [3] => Доминиканская Республика
    [4] => Нидерландские Антильские острова
    [5] => My Personal Republic
)

Is that what you want?

Posted by: Dag Apr 9 2020, 08:35 PM

QUOTE(Christian J @ Apr 9 2020, 10:31 PM) *

CODE
Array
(
    [0] => Нидерланды
    [1] => Caribbean Netherlands
    [2] => Република
    [3] => Доминиканская Республика
    [4] => Нидерландские Антильские острова
    [5] => My Personal Republic
)

Is that what you want?


Well, at first sight seems ok. I need to check code on my real case. To many passes I think... need about day to back here with results.

So far, do check real-life use. if size doesn't matter, speed does.
https://www.laban.rs/c/
https://www.laban.rs/c/eng/
https://www.laban.rs/c/rus/
https://www.laban.rs/c/srp/
https://www.laban.rs/c/eng/rt_data
https://www.laban.rs/c/rus/rt_data
https://www.laban.rs/c/srp/rt_data

Pages with full tables have sorting available...

Posted by: Dag Apr 12 2020, 01:01 PM

OK.
We don't need anything of that except one single line to compare execution.
My code is:

CODE

$text = str_replace($lgEng,$lgSec,$val[0]);

Your code is
CODE

if($text[$i]==$find[$j]) {
$text[$i]=$replace[$j];}

As text is always dirty enough with lot of slang, I need 2 passes with 2 differenet arrays: the second one is created manually and included in itself all unreplaced values (that array is not so big usually...). So, check by yourself both full codes. $lgEng is original source values and $corEng is array of values that have to be changed after first pass (remains unchanged)
What I am using:
CODE

foreach($abody as $val) {
    $tmp = str_replace($lgEng,$lgSec,$val[0]);    //- Only val[0] is to be changed (country name)
    $body = '<td>'.str_replace($corEng,$corSec,$tmp).'</td>';
    for($i = 1; $i < sizeof($val); $i++){    //- All of these are numbers
        $body .= '<td>'.$val[$i].'</td>';}
    $tbody .= "\t<tr>".$body."</tr>\n";
    $body = '';
}

Your code should looks like next:
CODE

foreach($abody as $val){
    $find = $lgEng;
    $replace = $lgSec;
    $text = $val;
    for($i=0; $i<count($text); $i++) {
        for($j=0; $j<count($find); $j++) {
            if($text[$i]==$find[$j]) {
                $tmp=$replace[$j]; //- don't need array here but string
                }
            }
        }
    $body = '<td>'.str_replace($corEng,$corSec,$tmp).'</td>';
    for($i = 1; $i < sizeof($val); $i++){    //- All of these are numbers
        $body .= '<td>'.$val[$i].'</td>';}
    $tbody .= "\t<tr>".$body."</tr>\n";
    $body = '';
}

The way 'IF strings are the same do replace' works better that simple str_replace but it is additional operation and execution will be slower. DB countries has 255 elements and those text of me about 200 so 200 times we are doing 255 checking and replacement or just replacement... Because second loop is neccessary anyway, I'll stand with simple str_replace.
IPB Image
ZIP Countries
http://www.laban.rs/files/Samples.zip


QUOTE(Dag @ Apr 9 2020, 08:18 PM) *

Will you retry with my samples?

QUOTE(Christian J @ Apr 9 2020, 03:10 PM) *

QUOTE(Christian J @ Apr 8 2020, 11:38 PM) *

but for some reason it returns this:

CODE
Array
(
    [0] => foo
    [1] => BAR
    [2] => foobar
)

[1] and [2] are what I expected, but shouldn't [0] be uppercase FOO? Haven't done any PHP in a long time. unsure.gif

I think I found the bug in my script above. The very first $j iteration works correct:

CODE
if($text[0]==$find[0]) // foo==foo

and does change "foo" to "FOO" in $textNew[0]. But in the next $j iteration:

CODE
if($text[0]==$find[1]) // foo!=bar

the IF compares "foo" with "bar", and because that's FALSE, $textNew[0] is changed again (this time by the ELSE condition) from "FOO" to the "foo" value of $text[0]).

This version might work better:

CODE
$find = array('foo', 'bar');
$replace = array('FOO', 'BAR');
$text = array('foo', 'bar', 'foobar');

$textNew=$text; // I first copy the whole array, only changing values later (if needed)

for($i=0; $i<count($text); $i++)
{
    for($j=0; $j<count($find); $j++)
    {
        if($text[$i]==$find[$j])
        {
            $textNew[$i]=$replace[$j]; // change array values only when needed (no need for ELSE condition)
        }
    }
}

echo '<pre>';
print_r($textNew);
echo '</pre>';




Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)