Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
how to explode even words in string of symbol "-"? for ex.:
$string = 'tshirt-blue-124-tshirt-blue-124-tshirt-blue-124';
or
$string = '333-red-333-red-333-red-333-red';
I need array like this:
$string[0] = 'tshirt-blue-124';
$string[1] = 'tshirt-blue-124';
$string[2] = 'tshirt-blue-124';
or
$string[0] = '333-red';
$string[1] = '333-red';
$string[2] = '333-red';
$string[3] = '333-red';
thanks
If it's always every three elements:
$string = 'tshirt-blue-124-tshirt-blue-124-tshirt-blue-124';
$newArray = array_chunk(explode('-', $string), 3);
array_walk(
$newArray,
function(&$value) {
$value = implode('-', $value);
});
var_dump($newArray);
EDIT
But you must know how many elements in advance:
$splitValue = 2;
$string = '333-red-333-red-333-red-333-red';
$newArray = array_chunk(explode('-', $string), $splitValue);
array_walk(
$newArray,
function(&$value) {
$value = implode('-', $value);
});
var_dump($newArray);
EDIT #2
If you have no idea how many elements that there in a repetition block, then look into the Lempel-Ziv-Welsh (LZW) compression algorithm. It is built on detecting repetitions in strings and utilizing them for compression. You can probably use a Suffix Trie datastructure to simplify the logic.
EDIT #3
As a simplistic approach to trying to identify the split size:
function getSplitSize($string) {
$splitSize = 2;
do {
$tempArray = array_chunk(explode('-', $string), $splitSize);
if ($tempArray[0] == $tempArray[1])
return $splitSize;
++$splitSize;
} while ($splitSize <= count($tempArray));
throw new Exception('No repetition found');
}
function splitStringOnRepetition($string) {
$newArray = array_chunk(explode('-', $string), getSplitSize($string));
array_walk(
$newArray,
function(&$value) {
$value = implode('-', $value);
}
);
return $newArray;
}
$string = 'tshirt-blue-124-tshirt-blue-124-tshirt-blue-124';
$array = splitStringOnRepetition($string);
var_dump($array);
$string = '333-red-333-red-333-red-333-red';
$array = splitStringOnRepetition($string);
var_dump($array);
For advanced yet efficient method, you can use a regular expression matching using preg_match():
$string = 'tshirt-blue-124-tshirt-blue-125-tshirt-blue-126';
$pattern = "/([A-Za-z]*-[A-Za-z]*-[\d]*)-?/";
preg_match_all($pattern, $string, $matches);
echo "<pre>";
print_r($matches[1]);
echo "</pre>";
and it will output:
Array
(
[0] => tshirt-blue-124
[1] => tshirt-blue-125
[2] => tshirt-blue-126
)
you can set the pattern the way you want..
Try with -
$string = 'tshirt-blue-124-tshirt-blue-124-tshirt-blue-124';
$new = explode('-', $string);
$i = 0;
$result = array();
while ($i < count($new)) {
$result[] = $new[$i].'-'.$new[$i+1].'-'.$new[$i+2];
$i += 3;
}
var_dump($result);
you can do something like this
$string = 'tshirt-blue-124-tshirt-blue-124-tshirt-blue-124';
$tmp = explode("-", $string);
while ($tmp) {
$output[] = implode('-', array_splice($tmp, 0, 3));
}
print_r($output);
Explode it
$string = explode("tshirt-", $string);
Now you have to add the value to each Array element
foreach($string as &$v){
$v = "tshirt-" . $v;
$v = rtrim($v, "-");
}
This is a very easy and simple to understand solution.
Related
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.
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++;
}
I want to be able to do something likes this:
$str="abc";
echo findNot($str); //will echo "defghijklomnopqrstuvwxyz"
$str2="happy birthday";
echo findNot($str2); //will echo "cfgjklmnoqsuvwxz"
Basically, it would find all letters not represented in the string and return them in an array or string.
I could do this easily with a foreach and arrays of characters, but I was wondering if anyone had a more elegant solution.
Here's what I came up with.
function findNot($str){
return array_diff(range('a','z'), array_unique(str_split(strtolower($str))));
}
How about this
$str="abc";
var_dump(findNot($str));
function findNot($string)
{
$letters = range('a', 'z');
$presents = array_map(function($i) { return chr($i); }, array_keys(array_filter(count_chars($string))));
return array_diff($letters, $presents);
}
PS: implode the result if you need a string of chars, not array
PPS: not sure if it is a "more elegant" solution :-)
PPPS: another solution I could think of is
$str="abc";
var_dump(findNot($str));
function findNot($string)
{
$letters = range('a', 'z');
$presents = str_split(count_chars($string, 4));
return array_intersect($letters, $presents);
}
You could do something like this:
$text = 'abcdefghijklmnop';
$search = array('a','b','c');
$result = str_replace($search, '', $text);
Zerk's solution is nice. I came up with this similar example, not as elegant.
<?php
$alphabet = 'abcdefghijklmnopqrstuvwxyz';
$alphabet = preg_split('//', $alphabet, -1, PREG_SPLIT_NO_EMPTY);
$str="abc";
var_dump( findNot($str) ); //will echo "defghijklomnopqrstuvwxyz"
$str2="happy birthday";
var_dump( findNot($str2) ); //will echo "cfgjklmnoqsuvwxz"
function findNot($str)
{
global $alphabet;
$str = str_replace(' ', '', $str);
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
$chars = array_unique($chars);
sort($chars);
$diff = array_diff($alphabet, $chars);
return $diff;
}
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]);
I have a string like this:
$string = "1,4|2,64|3,0|4,18|";
Which is the easiest way to access a number after a comma?
For example, if I have:
$whichOne = 2;
If whichOne is equal to 2, then I want to put 64 in a string, and add a number to it, and then put it back again where it belongs (next to 2,)
Hope you understand!
genesis'es answer with modification
$search_for = 2;
$pairs = explode("|", $string);
foreach ($pairs as $index=>$pair)
{
$numbers = explode(',',$pair);
if ($numbers[0] == $search_for){
//do whatever you want here
//for example:
$numbers[1] += 100; // 100 + 64 = 164
$pairs[index] = implode(',',$numbers); //push them back
break;
}
}
$new_string = implode('|',$pairs);
$numbers = explode("|", $string);
foreach ($numbers as $number)
{
$int[] = intval($number);
}
print_r($int);
$string = "1,4|2,64|3,0|4,18|";
$coordinates = explode('|', $string);
foreach ($coordinates as $v) {
if ($v) {
$ex = explode(',', $v);
$values[$ex[0]] = $ex[1];
}
}
To find the value of say, 2, you can use $whichOne = $values[2];, which is 64
I think it is much better to use the foreach like everyone else has suggested, but you could do it like the below:
$string = "1,4|2,64|3,0|4,18|";
$whichOne = "2";
echo "Starting String: $string <br>";
$pos = strpos($string, $whichOne);
//Accomodates for the number 2 and the comma
$valuepos = substr($string, $pos + 2);
$tempstring = explode("|", $valuepos);
$value = $tempstring[0]; //This will ow be 64
$newValue = $value + 18;
//Ensures you only replace the index of 2, not any other values of 64
$replaceValue = "|".$whichOne.",".$value;
$newValue = "|".$whichOne.",".$newValue;
$string = str_replace($replaceValue, $newValue, $string);
echo "Ending String: $string";
This results in:
Starting String: 1,4|2,64|3,0|4,18|
Ending String: 1,4|2,82|3,0|4,18|
You could run into issues if there is more than one index of 2... this will only work with the first instance of 2.
Hope this helps!
I know this question is already answered, but I did one-line solution (and maybe it's faster, too):
$string = "1,4|2,64|3,0|4,18|";
$whichOne = 2;
$increment = 100;
echo preg_replace("/({$whichOne},)(\d+)/e", "'\\1'.(\\2+$increment)", $string);
Example run in a console:
noice-macbook:~/temp% php 6642400.php
1,4|2,164|3,0|4,18|
See http://us.php.net/manual/en/function.preg-replace.php