PHP - Most efficient way to extract substrings based on given delimiter? - php

I have a string that contains some values I need to extract. Each of these values is surrounded by a common character.
What is the most efficient way to extract all of these values into an array?
For example, given the following string:
stackoverflowis%value1%butyouarevery%value2%
I would like to get an array containing value1 and value2

$s = "stackoverflowis%value1%butyouarevery%value2%";
preg_match_all('~%(.+?)%~', $s, $m);
$values = $m[1];
preg_match_all

$string = 'stackoverflowis%value1%butyouarevery%value2%';
$string = trim( $string, '%' );
$array = explode( '%' , $string );

$str = "stackoverflowis%value1%butyouarevery%value2%";
preg_match_all('/%([a-z0-9]+)%/',$str,$m);
var_dump($m[1]);
array(2) { [0]=> string(6) "value1" [1]=> string(6) "value2" }

Give a try to explode. Like $array = explode('%', $string);
LE:
<?php
$s = 'stackoverflowis%value1%butyouarevery%value2%';
$a = explode('%', $s);
$a = array_filter($a, 'strlen'); // removing NULL values
$last = ''; // last value inserted;
for($i=0;$i<=count($a);$i++)
if (isset($a[$i+1]) && $a[$i] <> $last)
$t[] = $last = $a[$i+1];
echo '<pre>'; print_r($t); echo '</pre>';

Use explode and take the odd-indexed values from the resulting array. You indicated you wanted the most efficient method, and this will be faster than a regex solution.
$str = 'stackoverflowis%value1%butyouarevery%value2%';
$arr = explode('%', $str);
$ct = count($arr);
for ($i = 1; $i < $ct; $i += 2) {
echo $arr[$i] . '<br />';
}

preg_match_all('/%([^%]+)%/', $s, $match);
var_dump($match[1]);

Related

Dynamic explosion with specific character

I am trying to extract a string in php and convert them to comma separated strings
Here are some sample string I am working with and the results I need:
input :
G1_C2_S3_T5 or G4_C5_S4_T7_I6_H3
Result must be :
G1,G1_C2,G1_C2_S3,G1_C2_S3_T5
or
G4,G4_C5,G4_C5_S4,G4_C5_S4_T7,G4_C5_S4_T7_I6,G4_C5_S4_T7_I6_H3
Input length can be dynamic for comma separation
Is this correct :
$arr = explode("_", $string, 2);
$first = $arr[0];
How can i do that in php?
Something like this should work, $string is the string you are working with
//explode by underscore
$parts = explode('_', $string);
$c = [];
//do until nothing else to pop from array
while (!empty($parts)) {
$c[] = implode('_', $parts);
//will pop element from end of array
array_pop($parts);
}
//reverse
$c = array_reverse($c);
//glue it with comma
echo implode(',', $c);
You should notice that the number of underscore-separated values in your initial string e.g. G4_C5_S4_T7_I6_H3 (6) is equal to the number of comma-separated values in your desired string e.g. G4,G4_C5,G4_C5_S4,G4_C5_S4_T7,G4_C5_S4_T7_I6,G4_C5_S4_T7_I6_H3 (6). So we'll use this number in our first loop $end = count($parts).
$str = "G4_C5_S4_T7_I6_H3";
$newstr = '';
$parts = explode('_', $str);
$comma = '';
for ($i = 0, $end = count($parts); $i < $end; $i++) {
$newstr .= $comma;
$underscore = '';
// build underscore-separated value
// index i is used to indicate up which value to stop at for each iteration
for ($j = 0; $j <= $i; $j++) {
$newstr .= $underscore . $parts[$j];
// set underscore after the first iteration of the loop
$underscore = '_';
}
// set comma after the first iteration of the loop
$comma = ',';
}
echo $newstr; // G4,G4_C5,G4_C5_S4,G4_C5_S4_T7,G4_C5_S4_T7_I6,G4_C5_S4_T7_I6_H3
The explosion is easy:
$parts = explode('_', $string);
Now you get a $parts array like [ 'G1', 'C2', 'S3', 'T5' ].
You want to convert this to an array so that each item is the concatenation of that item and every other item before it:
$prev = [ ];
array_walk(
$parts,
function(&$value) use (&$prev) {
$prev[] = $value;
$value = implode('_', $prev);
}
);
Now $parts holds the elements:
print implode(', ', $parts);
yields
G1, G1_C2, G1_C2_S3, G1_C2_S3_T5

Find characters in string that are present in an array and remove them - php

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...)
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>
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
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
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.
strtr($str, ['<' => '', '.' => '']);
This will probably outperform anything else, because it doesn't require you to iterate over anything in PHP.

Get string between two strings

My string is: "reply-234-private", i want to get the number after "reply-" and before "-private", it is "234". I have tried with following code but it returns an empty result:
$string = 'reply-234-private';
$display = preg_replace('/reply-(.*?)-private/','',$string);
echo $display;
You can just explode it:
<?php
$string = 'reply-234-private';
$display = explode('-', $string);
var_dump($display);
// prints array(3) { [0]=> string(5) "reply" [1]=> string(3) "234" [2]=> string(7) "private" }
echo $display[1];
// prints 234
Or, use preg_match
<?php
$string = 'reply-234-private';
if (preg_match('/reply-(.*?)-private/', $string, $display) === 1) {
echo $display[1];
}
Have a look at explode() function
something like this:
$myString = 'reply-234-private';
$myStringPartsArray = explode("-", $myString);
$answer = $myStringPartsArray[1];
This article show you, How to get of everything string between two tags or two strings.
http://okeschool.com/articles/312/string/how-to-get-of-everything-string-between-two-tag-or-two-strings
<?php
// Create the Function to get the string
function GetStringBetween ($string, $start, $finish) {
$string = " ".$string;
$position = strpos($string, $start);
if ($position == 0) return "";
$position += strlen($start);
$length = strpos($string, $finish, $position) - $position;
return substr($string, $position, $length);
}
?>
in case your question, you can try this :
$string1='reply-234-private';
echo GetStringBetween ($string1, "-", "-")
or we can use any 'identifier string' for grab the string between the identifier string. for example:
echo GetStringBetween ($string1, "reply-", "-private")
Use php's inbuilt regex support functions
preg_match_all
this would help, suppose you want the array of strings(keys) between ## in following example, where '/' doesn't fall in-between, you can built new example with different start an end variable
function getInbetweenStrings($start, $end, $str){
$matches = array();
$regex = "/$start([a-zA-Z0-9_]*)$end/";
preg_match_all($regex, $str, $matches);
return $matches[1];
}
$str = "C://##ad_custom_attr1##/##upn##/##samaccountname##";
$str_arr = getInbetweenStrings('##', '##', $str);
print_r($str_arr);
$myString = 'reply-234-private';
echo str_replace('-','',filter_var($myString,FILTER_SANITIZE_NUMBER_INT));
That should do the job.
If you want to do it in js, try this function -
function getStringBetween(str , fromStr , toStr){
var fromStrIndex = str.indexOf(fromStr) == -1 ? 0 : str.indexOf(fromStr) + fromStr.length;
var toStrIndex = str.slice(fromStrIndex).indexOf(toStr) == -1 ? str.length-1 : str.slice(fromStrIndex).indexOf(toStr) + fromStrIndex;
var strBtween = str.substring(fromStrIndex,toStrIndex);
return strBtween;
}

How can I tell the number of times a value from an array is in a string

Imagine I had an array called uselessKeywords. It has the values "and","but","the".
If I also have a string with "cool,and,but,and" in it, how can I tell how many times any values from the array are in the string?
Something along the lines of this would do, but you'd have to watch for false positives, such as andover and thesaurus.
$uselesskeywords = array('and', 'but', 'the');
$regex = implode('|', $uselesskeywords);
$count = count(preg_grep("/($regex)/", "cool,and,but,and"));
You could loop over the string with a foreach uselessKeywords
$count = 0;
foreach($uselessKeywords as $needle){
$count = $count + substr_count($str, $needle);
}
echo $count;
Improvement of Marc B (add some comas to eliminate the false positive andover and thesaurus; I've added lookahead because some values can be one by one):
$uselesskeywords = array('and', 'but', 'the');
$str = "cool,and,but,and";
$regex = implode('(?=,)|,', $uselesskeywords);
$count = count(preg_grep("/,$regex(?=,)/", ",$str,"));
Try this..
<?php
function uselessKeywordOccurances ($myString, $theArray) {
$occurances = array();
$myTestWords = preg_split("/,/", $myString);
for($i = 0; $i < count($myTestWords); $i++) {
$testWord = $myTestWords[$i];
if (in_array($testWord, $theArray)) {
array_push($occurances, $testWord);
}
}
$grouped = array_count_values($occurances);
arsort($grouped);
return $grouped;
}
$uselessKeywords = array("and", "but", "the");
$testWords = "cool,and,but,and,and,the,but,wonderful";
$result = uselessKeywordOccurances($testWords, $uselessKeywords);
var_dump($result);
?>
It should return occurrences of the uselessKeywords, like so..
array(3) { ["and"]=> int(3) ["but"]=> int(2) ["the"]=> int(1) }

php the best way to split string containing pairs of values

i have a string in the following format:
$str='a1_b1,a2_b2,a3_b3'
where a and b - some positive numbers. i need to split it to get two strings in format:
'a1,a2,a3' and 'b1,b2,b3'
the very primitive way would be:
$temp=explode(',', $str);
$str1='';
$str2='';
for($i=0;$i<count($temp);$i++){
$temp2=explode('_',$temp[$i]);
$str1.=$temp2[0].',';
$str2.=$temp2[1].',';
}
is it possible to do it more intelligent then just explode in loop?
Not much different from accepted answer but doing it with fewer code
<?php
$str = 'a1_b1,a2_b2,a3_b3';
$temp=explode(',', $str);
foreach($temp as $tem)
list($str_a[], $str_b[])=explode('_',$tem);
$str1 = implode(',', $str_a);
$str2 = implode(',', $str_b);
Probably the easiest way (which also happens to use the least amount of code and no loops) is to make use of PHP's parse_str() function:
// Assuming $str = 'a1_b1,a2_b2,a3_b3'
$str = str_replace([',', '_'], ['&', '='], $str);
parse_str($str, $arr);
// Your key/value pairs are now in $arr
$keys = implode(',', array_keys($arr));
$values = implode(',', array_values($arr));
Of course, parse_str() expects the standard foo=bar&baz=boz format, so if possible, you should use that format instead of foo_bar,baz_boz to save yourself a step. But, if that's not possible, then you can simply use str_replace() like I did above to make the appropriate substitutions.
Note: I used PHP 5.4 short array syntax [...]. If you're using < PHP 5.4, change it to array(...) instead.
The best way would be to organize the formatting of the string so that it doesnt come to this stage where you need to do this. But I'm assuming that you cant do that, therefore posting this question here,
What you did is a good way to do this unless you want to use regex.
$str = 'a1_b1,a2_b2,a3_b3' ;
$exp = explode(',', $str);
$a = array();
$b = array();
foreach($exp as $i)
{
$sep = explode('_', $i);
$a[] = $sep[0];
$b[] = $sep[1];
}
// at this point a and b are arrays so if you want to do better things to the data
// you can use arrays instead of manually concatenating the items with commas
$a_str = implode(',', $a); // a1,a2,a2
$b_str = implode(',', $b); // b1,b2,b2
$temp=explode(',', $str);
$str1='';
$str2='';
$str_a = array();
$str_b = array();
for($i=0;$i<count($temp);$i++){
$temp2=explode('_',$temp[$i]);
$str_a[]=$temp2[0];
$str_b[]=$temp2[1];
}
$str1 = implode(',', $str_a);
$str2 = implode(',', $str_b);
Oh, this is nothing more intelligent...
I can't really think of a better way of doing it. The best thing would be to not get in a situation where you need to do this in the first place but what can we do?
Just to provide another (not better) way of doing the same thing, you can use strtok.
$str='a1_b1,a2_b2,a3_b3';
$tok = strtok($str, "_,");
$i = 0;
$a = array();
$b = array();
while ($tok !== false) {
if ($i++ %2) $b[] = $tok;
else $a[] = $tok;
$tok = strtok("_,");
}
echo implode(',', $a); //a1,a2,a3
echo implode(',', $b); //b1,b2,b3
Your way is more clear and easier to understand, so I'd just stick with it.
Assuming PHP >= 5.3.0:
$str = 'a1_b1,a2_b2,a3_b3';
$array = array_map(function($n) { return explode("_", $n); }, explode(",", $str));
$aString = implode(",", array_map(function($n) { return $n[0]; }, $array));
$bString = implode(",", array_map(function($n) { return $n[1]; }, $array));
var_dump($aString);
var_dump($bString);
Output:
string 'a1,a2,a3' (length=8)
string 'b1,b2,b3' (length=8)
Still looping strictly speaking, but fancier :)
$str = 'a1_b1,a2_b2,a3_b3' ;
$arr = preg_split("/[\s,_]/" , $str);
$str1 = $str2 = '';
for($i=0; $i<count($arr); $i++) {
$str1 .= $arr[$i] ;
if(isset($arr[$i+1]))
$str2 .= $arr[$i+1];
if(isset($arr[$i+2])) {
$str1 .= ',';
$str2 .= ',';
}
$i++;
}

Categories