Splitting a string with conditions by Regex - php

I have a string like this
abcabdabeaf
Now I want to split it into a sequence of 'a', 'b' and any characters follow after the string 'ab' like this
Array
(
[0] => a
[1] => b
[2] => c
[3] => a
[4] => b
[5] => d
[6] => a
[7] => b
[8] => eaf
)
My current attempt is
$string = "abcabdabeaf";
$split = preg_split("/((?<=a)b)/", $string, -1, PREG_SPLIT_DELIM_CAPTURE);
print_r($split);
But the result is
Array
(
[0] => a
[1] => b
[2] => ca
[3] => b
[4] => da
[5] => b
[6] => eaf
)
Is it possible to do so with regex?

Personally I find it easier to think of this problem in terms of matching instead of splitting:
Match a (if followed by b)
Match b (if it follows a)
Match anything else until 'ab' or end of string is encountered
In code:
preg_match_all('/a(?=b)|(?<=a)b|.*?(?=ab|$)/', $s, $matches);
// note that $matches[0] has an empty array element at the end
This would work too, albeit a bit more verbose than I'd like:
$final = array(); $first = true;
foreach (explode('ab', $s) as $part) {
if ($first) {
$first = false;
} else {
$final[] = 'a';
$final[] = 'b';
}
$final[] = $part;
}

Why do you want to use regular expressions? explode() is right down your alley.
<?php $k = "abcabdefabcabcgfgdgdfabde";
var_dump(explode("ab",$k));
?>
You will get an empty element if your string starts with ab. To rememdy it, simply array_shift the array!

Related

Find occurrences of length of words in array

I'm trying to find the number of occurrences length in array;
Here's what I've tried, but I don't know what to do after.
function instances_and_count($input) {
$arr = explode(' ', $input);
$count = 0;
$test = [];
foreach ($arr as $arr_str) {
if ($count != 0) {
$test = [$count => 'hi'];
print_r($test);
}
$count++;
}
}
$test = 'A heard you say something I know you ain\'t trying to take me homeboy.';
instances_and_count($test);
In this example, I explode a string to make an array. I need a count of let's say all words with a length of 1 which in this string it's a count of 2 (A and I); How can I do this for all lengths?
PHP's array functions are really useful here; we can convert our exploded array of strings to an array of string lengths using array_map and strlen, and then use array_count_values to count how many words of each length there are:
$test = 'A heard you say something I know you ain\'t trying to take me homeboy.';
$counts = array_count_values(array_map('strlen', explode(' ', $test)));
print_r($counts);
Output:
Array
(
[1] => 2
[5] => 2
[3] => 3
[9] => 1
[4] => 2
[6] => 1
[2] => 2
[8] => 1
)
Demo on 3v4l.org
Note that there is a length of 8 in this array for the "word" homeboy. This can be avoided either by stripping trailing punctuation from the string, or (better) using str_word_count to extract only whole words from the original string. For example (thanks #mickmackusa):
$test = 'I heard you say something I know you ain\'t trying to take me homeboy.';
$counts = array_count_values(array_map('strlen', str_word_count($test, 1)));
print_r($counts);
Output:
Array
(
[1] => 2
[5] => 2
[3] => 3
[9] => 1
[4] => 2
[6] => 1
[2] => 2
[7] => 1
)
Demo on 3v4l.org
If you want to output the array with keys in order, just use ksort on it first:
ksort($counts);
print_r($counts);
Output:
Array
(
[1] => 2
[2] => 2
[3] => 3
[4] => 2
[5] => 2
[6] => 1
[8] => 1
[9] => 1
)
This is not necessary for use within your application.
Use the length of the word as array key. For each word you are looping over, check if an array entry for that length already exists - if so, increase the value by one, otherwise initialize it with 1 at that point:
function instances_and_count($input) {
$words = explode(' ', $input);
$wordLengthCount = [];
foreach($words as $word) {
$length = strlen($word);
if(isset($wordLengthCount[$length])) {
$wordLengthCount[$length] += 1;
}
else {
$wordLengthCount[$length] = 1;
}
}
ksort($wordLengthCount);
return $wordLengthCount;
}
Result:
array (size=8)
1 => int 2
2 => int 2
3 => int 3
4 => int 2
5 => int 2
6 => int 1
8 => int 1
9 => int 1

Convert string with two delimiters into flat associative array [duplicate]

This question already has answers here:
Explode a string to associative array without using loops? [duplicate]
(10 answers)
Closed 7 months ago.
I'm really have no idea about regex...
So I got stuck... Can anyone give me a solution with explanation of regex itself?
Here is my code:
$str = "id:521082299088|name:JOHNSON GREIG DENOIA|mounth:JAN17|amount:170027|admin:2500|billqty:1|metre:R1/900|usage:00010261-00010550|reffno:0BKP21851AF3EC2E0D4F56997EA19DFA|charge:170377|balace:1935";
$pregsplit = preg_split("/[\s|]+/",$string2);
Output:
Array
(
[0] => id:521082299088
[1] => name:JOHNSON
[2] => GREIG
[3] => DENOIA
[4] => mounth:JAN17
[5] => amount:170027
[6] => admin:2500
[7] => billqty:1
[8] => metre:R1/900
[9] => usage:00010261-00010550
[10] => reffno:0BKP21851AF3EC2E0D4F56997EA19DFA
[11] => charge:170377
[12] => balance:1935
)
I want output like this:
Array
(
"id" => 521082299088
"name" => "JOHNSON GREIG DENOIA"
"mount" => "JAN17"
"amount" => 170027
"admin" => 2500
"billqty" => 1
"metre" => "R1/900"
"usage" => "00010261-00010550"
"reffno" => "0BKP21851AF3EC2E0D4F56997EA19DFA"
"charge" => 170377
"balance" => 1935
)
1) The solution using preg_match_all function with specific regex pattern:
$str = "id:521082299088|name:JOHNSON GREIG DENOIA|mounth:JAN17|amount:170027|admin:2500|billqty:1|metre:R1/900|usage:00010261-00010550|reffno:0BKP21851AF3EC2E0D4F56997EA19DFA|charge:170377|balace:1935";
preg_match_all("/(\w+):([^|]+)/", $str, $matches, PREG_SET_ORDER);
$result = [];
foreach ($matches as $items) {
$result[$items[1]] = $items[2];
}
// $items[1] contains a "parameter" name captured by the first capturing group (\w+)
// $items[2] contains a "parameter" value captured by the second capturing group ([^|]+)
print_r($result);
The output:
Array
(
[id] => 521082299088
[name] => JOHNSON GREIG DENOIA
[mounth] => JAN17
[amount] => 170027
[admin] => 2500
[billqty] => 1
[metre] => R1/900
[usage] => 00010261-00010550
[reffno] => 0BKP21851AF3EC2E0D4F56997EA19DFA
[charge] => 170377
[balace] => 1935
)
(\w+) - matches all alphanumeric characters followed by :
([^|]+) - matches all characters excepting | which is delimiter
http://php.net/manual/en/function.preg-match-all.php
2) In addition to the first approach - using array_combine function(to combine all respective values from two capturing groups):
preg_match_all("/(\w+):([^|]+)/", $str, $matches);
$result = array_combine($matches[1], $matches[2]);
// will give the same result
3) The third alternative approach would be using explode() function:
$result = [];
foreach (explode("|", $str) as $items) {
$pair = explode(":", $items);
$result[$pair[0]] = $pair[1];
}
If you are unable to write regular expression.Here is a simple solution using explode() method.The explode() function breaks a string into an array.
<?php
$str = "id:521082299088|name:JOHNSON GREIG DENOIA|mounth:JAN17|amount:170027|admin:2500|billqty:1|metre:R1/900|usage:00010261-00010550|reffno:0BKP21851AF3EC2E0D4F56997EA19DFA|charge:170377|balace:1935";
$array = explode('|',$str);
foreach($array as $key=>$value){
$data = explode(':',$value);
$final[$data[0]] = $data[1];
}
print_r($final);
?>
Output:
Array
(
[id] => 521082299088
[name] => JOHNSON GREIG DENOIA
[mounth] => JAN17
[amount] => 170027
[admin] => 2500
[billqty] => 1
[metre] => R1/900
[usage] => 00010261-00010550
[reffno] => 0BKP21851AF3EC2E0D4F56997EA19DFA
[charge] => 170377
[balace] => 1935
)
To learn more about explode() read docs http://php.net/manual/en/function.explode.php
A funny way (only if your string doesn't contain = or &): translate pipes to ampersands and colons to equal signs, then parse it as an URL query with parse_str:
$str = "id:521082299088|name:JOHNSON GREIG DENOIA|mounth:JAN17|amount:170027|admin:2500|billqty:1|metre:R1/900|usage:00010261-00010550|reffno:0BKP21851AF3EC2E0D4F56997EA19DFA|charge:170377|balace:1935";
parse_str(strtr($str, ':|', '=&'), $result);
print_r($result);
demo
This approach would be an alternative.
You can separate string and create an array from it using PHP's explode() function. Then you can separate the 'key:value' structure using strpos() and substr() functions.
// input string
$str = "id:521082299088|name:JOHNSON GREIG DENOIA|mounth:JAN17|amount:170027|admin:2500|billqty:1|metre:R1/900|usage:00010261-00010550|reffno:0BKP21851AF3EC2E0D4F56997EA19DFA|charge:170377|balace:1935";
// make an array out of the string, split elements on each pipe character ('|')
$arr = explode('|', $str);
// create an output array to keep the results
$output = [];
// process the array
foreach ($arr as $item) {
// get delimiter
$separatorPos = strpos($item, ':');
// take the key part (The part before the ':')
$key = substr($item, 0, $separatorPos);
// take the value part (The part after the ':')
$value = substr($item, $separatorPos);
// push it into the output array
$output[$key] = $value;
}
// dump the output array
var_export($output);
Dump of the output array would be like follwing;
[
'id' => ':521082299088',
'name' => ':JOHNSON GREIG DENOIA',
'mounth' => ':JAN17',
'amount' => ':170027',
'admin' => ':2500',
'billqty' => ':1',
'metre' => ':R1/900',
'usage' => ':00010261-00010550',
'reffno' => ':0BKP21851AF3EC2E0D4F56997EA19DFA',
'charge' => ':170377',
'balace' => ':1935',
]

How to extract multiple values from a string to call an array?

I want to extract values from a string to call an array for basic template functionality:
$string = '... #these.are.words-I_want.to.extract# ...';
$output = preg_replace_callback('~\#([\w-]+)(\.([\w-]+))*\#~', function($matches) {
print_r($matches);
// Replace matches with array value: $these['are']['words-I_want']['to']['extract']
}, $string);
This gives me:
Array
(
[0] => #these.are.words-I_want.to.extract#
[1] => these
[2] => .extract
[3] => extract
)
But I'd like:
Array
(
[0] => #these.are.words-I_want.to.extract#
[1] => these
[2] => are
[3] => words-I_want
[4] => to
[5] => extract
)
Which changes do I need to make to my regex?
It seems that the words are simply dot separated, so match sequences of what you don't want:
preg_replace_callback('/[^#.]+/', function($match) {
// ...
}, $str);
Should give the expected results.
However, if the # characters are the boundary of where the matching should take place, you would need a separate match and then use a simple explode() inside:
preg_replace_callback('/#(.*?)#/', function($match) {
$parts = explode('.', $match[1]);
// ...
}, $str);
You can use array_merge() function to merge the two resulting arrays:
$string = '... #these.are.words-I_want.to.extract# ...';
$result = array();
if (preg_match('~#([^#]+)#~', $string, $m)) {
$result[] = $m[0];
$result = array_merge($result, explode('.', $m[1]));
}
print_r($result);
Output:
Array
(
[0] => #these.are.words-I_want.to.extract#
[1] => these
[2] => are
[3] => words-I_want
[4] => to
[5] => extract
)

empty return preg_split [how]?

i have string like this
$string = '$foo$wow$123$$$ok$';
i want to return empty string and save string in array like this
0 = foo
1 = wow
2 = 123
3 =
4 =
5 = ok
i use PREG_SPLIT_NO_EMPTY, i know when make PREG_SPLIT_NO_EMPTY return is not empty, but i want any result empty, i want my result save in variable array like in PREG_SPLIT_NO_EMPTY with $chars[$i];
this is my preg_split :
$chars = preg_split('/[\s]*[$][\s]*/', $string, -1, PREG_SPLIT_NO_EMPTY);
for($i=0;$i<=5;$i++){
echo $i.' = '.$chars[$i];
}
i want, my result show with looping. no in object loop i want pure this looping:
for($i=0;$i<=5;$i++){
echo $i.' = '.$chars[$i];
}
to show my result.
how i use this preg_split,
thanks for advance...
use explode
$str = '$foo$wow$123$$$ok$';
$res = explode ("$",$str);
print_r($res);
Array
(
[0] =>
[1] => foo
[2] => wow
[3] => 123
[4] =>
[5] =>
[6] => ok
[7] =>
)
Using explode adds the empty entrys to the front and the back.
This one matches the tc's expected output:
$str = '$foo$wow$123$$$ok$';
preg_match_all("#(?<=\\$)[^\$]*(?=\\$)#", $str, $res);
echo "<pre>";
print_r($res);
echo "</pre>";
[0] => Array
(
[0] => foo
[1] => wow
[2] => 123
[3] =>
[4] =>
[5] => ok
)

Splitting String into array and display it by chunk

foreach($files as $file) {
$xname = basename($file['name'],'.jpg');
$tmp = preg_split("/[\s,-]+/",$xname,-1, PREG_SPLIT_NO_EMPTY);
echo "<pre>";
print_r($tmp);
echo "</pre>";
here is the example string "LR-147-TKW FLOWER RECT MIRROR FRAME"
I have this line of code that splits my string to arrays. What i want it do is to get the first 3 words which is "LR-147-TKW" and store it to a variable. how can i achieve this?
my array output is this 0] => BR
[1] => 139
[2] => TKW
[3] => DRESSER
[4] => BUFFET
[5] => MIRROR
You can use explode(), here are some examples:
<?php
$str = 'LR-147-TKW FLOWER RECT MIRROR FRAME';
$parts = explode(' ',$str);
print_r($parts);
/*
Array
(
[0] => LR-147-TKW
[1] => FLOWER
[2] => RECT
[3] => MIRROR
[4] => FRAME
)
*/
$serial_parts = explode('-',$parts[0]);
print_r($serial_parts);
/*
Array
(
[0] => LR
[1] => 147
[2] => TKW
)
*/
$full = array_merge($serial_parts,$parts);
print_r($full);
/*
Array
(
[0] => LR
[1] => 147
[2] => TKW
[3] => LR-147-TKW
[4] => FLOWER
[5] => RECT
[6] => MIRROR
[7] => FRAME
)
*/
?>
this actually does the trick for you current input. $tmp will contain LR-147-TKW after you execute this line of code:
list($tmp) = explode(' ', $input);
This is because preg_split("/[\s,-]+/",... splits your string where ever a comma, minus or space occurs. Change it to preg_split("/[\s,]+/",...) and it should give you the correct array.
Note that if you do that, your function won't split words like WELL-SPOKEN. It will become one entry in your array.
Considering your string has same pattern.
$str = "LR-147-TKW FLOWER RECT MIRROR FRAME";
$str1 = explode(' ',$str);
echo $str1[0];
How about using explode :
$arr = explode(' ',$file);
echo arr[0];
using preg_split is a bit of overkill for such a simple task...
If you want to avoid the array, it can be done using strpos and substr:
$pos = strpos($file, ' ');
echo substr('abcdef', 0, $pos);
add to your code:
$tmp = array_slice($tmp,0,3);

Categories