3

Let's say i have the following string: $test ='abcd.gdda<fsa>dr';

And the following array: $array = array('<','.');

How can i find the positions of the characters that are elements in the $array array? (fastest way possible) and then store and remove them (without leaving NULL values at that specific index)?

Ps. I know that i could use strpos() to check for each element but that would output something like: 9, 5 because the '<' symbol is searched for before the '.' element and that causes the function to believe that the '<' is before '.' in the string. I tried combining this with the sort() function...but i does not work as expected... (it outputs some NULL positions...)

SpiderLinked
  • 363
  • 1
  • 6
  • 14
  • Instead of `strpos()` use `strrpos()`, start looking for string for right to left. So when you replace `<`, character `.` will still be on same position. – Glavić Dec 28 '13 at 11:22
  • if i use this method...how will i check for all the occurrences? this will always stop after finding the first element... – SpiderLinked Dec 28 '13 at 11:27
  • Do you also need to store positions for every search character separately? Or just positions in which any of those characters were found? – Cthulhu Dec 28 '13 at 11:30
  • @Cthulhu yes i do...and in ascending order too – SpiderLinked Dec 28 '13 at 11:31
  • **[Here you have a demo](https://eval.in/83692)** of this duplicated question: [PHP Find all occurrences of a substring in a string](http://stackoverflow.com/questions/15737408/php-find-all-occurrences-of-a-substring-in-a-string) – Glavić Dec 28 '13 at 11:32
  • that only checks for one string not a whole array of them.. – SpiderLinked Dec 28 '13 at 11:33
  • @SpiderLinked: that is a minimal upgrade. Have you looked at my demo? – Glavić Dec 28 '13 at 11:35

5 Answers5

3

Works with both strings and characters:

<?php
    $test ='abcda.gdda<fsa>dr';
    $array = array('<', '.', 'dr', 'a'); // not also characters but strings can be used
    $pattern = array_map("preg_quote", $array);
    $pattern = implode("|", $pattern);
    preg_match_all("/({$pattern})/", $test, $matches, PREG_OFFSET_CAPTURE);
    array_walk($matches[0], function(&$match) use (&$test)
    {
        $match = $match[1];
    });
    $test = str_replace($array, "", $test);
    print_r($matches[0]); // positions
    echo $test;

Output:

Array
(
    [0] => 0
    [1] => 4
    [2] => 5
    [3] => 9
    [4] => 10
    [5] => 13
    [6] => 15
)
bcdgddfs>
revo
  • 47,783
  • 14
  • 74
  • 117
  • This example only works on characters who are 1char long, [example](https://eval.in/83707). Can you fix that? – Glavić Dec 28 '13 at 12:16
  • @Glavić However OP needs to find character positions not strings, but yes I'll. – revo Dec 28 '13 at 12:18
  • I was thinking of users that will come here with same problem, so why not support multichar position already. – Glavić Dec 28 '13 at 12:21
1

Find all positions, store them in array:

$test = 'abcd.gdda<fsa>dr<second . 111';
$array = array('<','.');
$positions = array();

foreach ($array as $char) {
    $pos = 0;
    while ($pos = strpos($test, $char, $pos)) {
        $positions[$char][] = $pos;
        $pos += strlen($char);
    }
}

print_r($positions);
echo str_replace($array, '', $test);

demo

Glavić
  • 42,781
  • 13
  • 77
  • 107
  • it looks ok...however .. how can i combine the results so that i have only one array with elements in ascending order not a 2 dimension array? – SpiderLinked Dec 28 '13 at 11:42
  • @SpiderLinked: why would you need that? You can get array of `<` positions like `$positions['<']`. If you still wish to have all positions in one array, then you will have to make up a key, that cannot repeat, like `char` => `position` or smth like that. – Glavić Dec 28 '13 at 11:48
  • i need that because i need to use those positions easily... my array is made up of 47 elements and i can not use $position[$char][]...for everything...plus ..i need to have all the positions in ascending order.. – SpiderLinked Dec 28 '13 at 11:50
  • @SpiderLinked: like I said, then you must create some special keys that can't repeat, like this: [demo](https://eval.in/83702). If you don't need to know what char is on what position, then that is even easier: [demo](https://eval.in/83704). – Glavić Dec 28 '13 at 11:53
  • can't i just implode the array and then use str_split? – SpiderLinked Dec 28 '13 at 11:58
  • @SpiderLinked: why? What exactly do you need? Are 2 demo examples in my previous comment not ok? – Glavić Dec 28 '13 at 12:02
  • i mean to implode the array given by your example...because i need to use those position to get characters from another string...and this is why i need uni-dimensional arrays... – SpiderLinked Dec 28 '13 at 12:05
  • @SpiderLinked: ofcourse you can implode the array, you can do with it what ever you need in your project. – Glavić Dec 28 '13 at 12:07
  • WHY YOU NO USE str_replace :) – Rahul Prasad Dec 28 '13 at 13:36
  • @RAHULPRASAD: `str_replace()` is used... Last line in my answer. – Glavić Dec 28 '13 at 13:39
0

Here is one possible solutions, depending on every searching element being a single character.

$array = array(',', '.', '<');
$string = 'fdsg.gsdfh<dsf<g,gsd';

$search = implode($array); $last = 0; $out = ''; $pos = array();
foreach ($array as $char) $pos[$char] = array();

while (($len = strcspn($string, $search)) !== strlen($string)) {
    $last = ($pos[$string[$len]][] = $last + $len) + 1;
    $out .= substr($string, 0, $len);
    $string = substr($string, $len+1);
}
$out.=$string;

Demo: http://codepad.org/WAtDGr7p

Cthulhu
  • 1,379
  • 1
  • 13
  • 25
0

EDIT:
PHP has an inbuild function for that

str_replace($array, "", $test);

ORIGINAL ANSWER:
Here is how I would do it:

<?php
$test ='abcd.gdda<fsa>dr';
$array = array('<','.');
foreach($array as $delimiter) {
  // For every delimiter explode the text into array and the recombine it
  $exploded_array = explode($delimiter, $test);
  $test = implode("", $exploded_array);
}
?>

There are faster ways to do it (you will gain some microseconds) but why would you use php if you wanted speed :) I mostly prefer simplicity.

Rahul Prasad
  • 8,074
  • 8
  • 43
  • 49
-1
strtr($str, ['<' => '', '.' => '']);

This will probably outperform anything else, because it doesn't require you to iterate over anything in PHP.

Alexei Averchenko
  • 1,706
  • 1
  • 16
  • 29