Stop explode after certain index [duplicate] - php

This question already has answers here:
How to limit the elements created by explode()
(4 answers)
Closed 1 year ago.
How can I stop explode function after certain index.
For example
<?php
$test="The novel Prognosis Negative by Art Vandelay expresses protest against many different things. The story covers a great deal of time and takes the reader through many different places and events, as the author uses several different techniques to really make the reader think. By using a certain type of narrative structure, Vandelay is able to grab the reader’s attention and make the piece much more effective and meaningful, showing how everything happened";
$result=explode(" ",$test);
print_r($result);
?>
What if want to use only first 10 elements ($result[10])
How can I stop explode function once 10 elements are filled.
One way is to first trim the string upto first 10 spaces (" ")
Is there any other way, I don't want to store the remaining elements after limit anywhere (as done using positive limit parameter)?

What's about that third parameter of the function?
array explode ( string $delimiter , string $string [, int $limit ] )
check out the $limit parameter.
Manual: http://php.net/manual/en/function.explode.php
An example from the manual:
<?php
$str = 'one|two|three|four';
// positive limit
print_r(explode('|', $str, 2));
// negative limit (since PHP 5.1)
print_r(explode('|', $str, -1));
?>
The above example will output:
Array (
[0] => one
[1] => two|three|four ) Array (
[0] => one
[1] => two
[2] => three )
In your case:
print_r(explode(" " , $test , 10));
According to the php manual , when you're using the limit parameter:
If limit is set and positive, the returned array will contain a
maximum of limit elements with the last element containing the rest of
string.
Therefore , you need to get rid of the last element in the array.
You can do it easily with array_pop (http://php.net/manual/en/function.array-pop.php).
$result = explode(" " , $test , 10);
array_pop($result);

You could read the documentation for explode:
$result = explode(" ", $test, 10);

Related

PHP count instances of array items in a string

In PHP 7.3:
Given this array of low relevancy keywords...
$low_relevancy_keys = array('guitar','bass');
and these possible strings...
$keywords_db = "red white"; // desired result 0
$keywords_db = "red bass"; // desired result 1
$keywords_db = "red guitar"; // desired result 1
$keywords_db = "bass guitar"; // desired result 2
I need to know the number of matches as described above. A tedious way is to convert the string to a new array ($keywords_db_array), loop through $keywords_db_array, and then loop through $low_relevancy_keys while incrementing a count of matches. Is there a more direct method in PHP?
The way you described in your question but using array_* functions:
echo count(array_intersect(explode(' ', $keywords_db), $low_relevancy_keys));
(note that you can replace explode with preg_split if you need to be more flexible)
or using preg_match_all (that returns the number of matches):
$pattern = '~\b' . implode('\b|\b', $low_relevancy_keys) . '\b~';
echo preg_match_all($pattern, $keywords_db);
demo

Why should one use str_split() in php?

Given the following code :
$str = 'CLAX';
echo $str[2]; //prints 'A'
then why should I use str_split( $str ) to convert string to a array of characters ?
I understand str_split( $str , 2 ) will return array of strings; each string being 2 characters long.
http://php.net/manual/en/function.str-split.php
This function is to split a string into an array with given string split length
By default string split length is set 1
If you want to split a string into given in given length, then you can use str_split. But in your case you are splitting string with default length 1 that is by you are getting confused.
<?php
$str = "CLAX";
echo $str[2]; //here you are referring to 2 index of string
$arr2 = str_split($str);
Array
(
[0] => C
[1] => L
[2] => A
[3] => X
)
echo $str[2]; //here you are referring to 2 index of an array
str_split reference
<?php
$str = "Hello Friend";
$arr2 = str_split($str, 3);
Array
(
[0] => Hel
[1] => lo
[2] => Fri
[3] => end
)
Using str_split() comes in pretty handy when you want to leverage array functions to perform a task on the components in a string.
str_split() works like explode() except it doesn't care what the characters are, just their position in the string -- there are specific use cases for this.
Use Case #1: Group Array Elements by Letter Range
Rather than manually declaring an array with 3 letters per element, like this:
$chunks=['ABC','DEF','GHI','JKL','MNO','PQR','STU','VWX','YZ']
The same array can be produced with:
$chunks=str_split(implode(range('A','Z')),3);
This purely for demonstration. Of course, declaring it manually would be more efficient. The potential benefit for other cases is code flexibility and ease of code modification.
Use Case #2: Convert string to array at different character occurence
Use str_split() when using a foreach loop to process each character.
$string="abbbaaaaaabbbb";
$array=str_split($string);
$last="";
foreach($array as $v){
if(!$last || strpos($last,$v)!==false){
$last.=$v;
}else{
$result[]=$last;
$last=$v;
}
}
$result[]=$last;
var_export($result);
If you try to supply the foreach loop with $string php will choke on it. str_split() is the right tool for this job.
Use Case #3: Find element of an array those contains only specific character set in PHP
Use str_split() to in association with other array functions to check values in a way that string functions are not well suited for.
[I'll refrain from transferring the full code block across.]

Adding Character between numbers

I have an integer $client_version=1000 I do need to add dots between every number in this integer so it looks like 1.0.0.0 and save it in new variable as string.
How can I do this?
Easy enough:
$client_version = 1000;
$dotted = join(".",str_split($client_version));
Note that this will always split it so that there is only one character between the dots. If you want something like 1.00.0, you'll need to change your question to explain more about what you're trying to do and what patterns you need.
PHP offers the function array str_split ( string $string [, int $split_length = 1 ] ) to convert a string to a character-array or blocks of characters.
In your case, invoking str_split((string)1000, 1) or str_split((string)1000) will result in:
Array
(
[0] => 1
[1] => 0
[2] => 0
[3] => 0
)
Code:
implode('.',str_split((string)1000))
Result: 1.0.0.0
For a more general, yet less well known approach, based on Regular Expression see this gist and this tangentially related topic on SO.
Code:
preg_match_all('/(.{1})/', (string)1000, $matches);
echo implode('.', $matches[0]);
Result: 1.0.0.0
Use str_split to get an array of chars and then implode them.
$client_version = 1000;
$client_version_chars = str_split($client_version);
$client_version_with_dots = implode('.', $client_version_chars);

Efficient way to parse this string into array in PHP?

Background
I have an array which I create by splitting a string based on every occurrence of 0d0a using preg_split('/(?<=0d0a)(?!$)/').
For example:
$string = "78781110d0a78782220d0a";
will be split into:
Array ( [0] => 78781110d0a [1] => 78782220d0a )
A valid array element has to start with 7878 and end with 0d0a.
The Problem
But sometimes, there's an additional 0d0a in the string which splits into an extra and invalid array element, i.e., that doesn't begin with 7878.
Take this string for example:
$string = "78781110d0a2220d0a78783330d0a";
This is split into:
Array ( [0] => 78781110d0a [1] => 2220d0a [2] => 78783330d0a )
But it should actually be:
Array ( [0] => 78781110d0a2220d0a [1] => 78783330d0a)
My Solution
I've written the following (messy) code to get around this:
$data = Array('78781110d0a','2220d0a','78783330d0a');
$i = 0; //count for $data array;
$j = 0; //count for $dataFixed array;
$dataFixed = $data;
foreach($data as $packet) {
if (substr($packet,0,4) != "7878") { //if packet doesn't start with 7878, do some fixing
if ($i != 0) { //its the first packet, can't help it!
$j++;
if ((substr(strtolower($packet), -4, 4) == "0d0a")) { //if the packet doesn't end with 0d0a, its 'mostly' not valid, so discard it
$dataFixed[$i-$j] = $dataFixed[$i-$j] . $packet;
}
unset($dataFixed[$i-$j+1]);
$dataFixed = array_values($dataFixed);
}
}
$i++;
}
Description
I first copy the array to another array $dataFixed. In a foreach loop of the $data array, I check whether it starts with 7878. If it doesn't, I join it with the previous array in $data. I then unset the current array in $dataFixed and reset the array elements with array_values.
But I'm not very confident about this solution.. Is there a better, more efficient way?
UPDATE
What if the input string doesn't end in 0d0a like its supposed to? It will stick to the previous array element..
For e.g.: in the string 78781110d0a2220d0a78783330d0a0000, 0000 should be separated as another array element.
Use another positive lookahead (?=7878) to form:
preg_split('/(?<=0d0a)(?=7878)/',$string)
Note: I removed (?!$) because I wasn't sure what that was for, based on your example data.
For example, this code:
$string = "78781110d0a2220d0a78783330d0a";
$array = preg_split('/(?<=0d0a)(?=7878)(?!$)/',$string);
print_r($array);
Results in:
Array ( [0] => 78781110d0a2220d0a [1] => 78783330d0a )
UPDATE:
Based on your revised question of having possible random characters at the end of the input string, you can add three lines to make a complete program of:
$string = "78781110d0a2220d0a787830d0a330d0a0000";
$array = preg_split('/(?<=0d0a)(?=7878)/',$string);
$temp = preg_split('/(7878.*0d0a)/',$array[count($array)-1],null,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
$array[count($array)-1] = $temp[0];
if(count($temp)>1) { $array[] = $temp[1]; }
print_r($array);
We basically do the initial splitting, then split the last element of the resulting array by the expected data format, keeping the delimiter using PREG_SPLIT_DELIM_CAPTURE. The PREG_SPLIT_NO_EMPTY ensures we won't get an empty array element if the input string doesn't end in random characters.
UPDATE 2:
Based on your comment below where it seems you're implying there might be random characters between any of the desired matches, and you want these random characters preserved, you could do this:
$string = "0078781110d0a2220d0a2220d0a0000787830d0a330d0a000078781110d0a2220d0a0000787830d0a330d0a0000";
$split1 = preg_split('/(7878.*?0d0a)/',$string,null,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
$result = array();
foreach($split1 as $e){
$split2 = preg_split('/(.*0d0a)/',$e,null,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
foreach($split2 as $el){
// test if $el doesn't start with 7878 and ends with 0d0a
if(strpos($el,'7878') !== 0 && substr($el,-4) == '0d0a'){
//if(preg_match('/^(?!7878).*0d0a$/',$el) === 1){
$result[ count($result)-1 ] = $result[ count($result)-1 ] . $el;
} else {
$result[] = $el;
}
}
}
print_r($result);
The strategy employed here is different than above. First we split the input string based on the delimiter that matches your desired data, using the nongreedy regex .*?. At this point we have some strings that contain the ending of a desired value and some garbage at the end, so we split again based on the last occurrence of "0d0a" with the greedy regex .*0d0a. We then append any of those resulting values that don't start with "7878" but end with "0d0a" to the previous value, as this should repair the first and second halves that got split because it contained an extra "0d0a".
I provided two methods for the innermost if statement, one using regular expressions. The regex one is marginally slower in my testing, so I've left that one commented out.
I might still not have your full requirements, so you'll have to let me know if it works and perhaps provided your full dataset.
I think you are using a delimiter "0d0a" which also happens to be part of a content! Its not possible to avoid getting junk data as long as delimiter can also be part of content. Somehow delimiter must be unique.
Possible solutions.
Change the delimited to something else that doesn't occur as part of your data ( 000000, #!.;)
If you are definite about length of text that easy arrange item may have, use it. As per examples its not possible.
Solutions given in answers considering only sample data you have shared. If you are confidant about what will be the content of string, then these solutions given by others are pretty good to use. Otherwise these solutions wont assure you guarantee!
Best solution: Fix right delimiter then use regex or explode whatever you prefer.
Why don't you use preg_match_all instead? You can avoid all of the non-capturing groups (the look aheads, look behinds) in order to split the string (which without the non-capturing groups removes the matches), and just find the matches you're looking for:
Updated
<?php
$string = "00787817878110d0a22278780d0a78783330d0a00";
preg_match_all('/7878.*?0d0a(?=7878|[^(7878)]*?$)/', $string, $arr);
print_r($arr);
?>
Gives an array $arr[0] => ( [0] => 787817878110d0a22278780d0a, [1] => 78783330d0a ). Strips leading and trailing garbage characters (whatever doesn't start with 7878 or end with 7878 or 0d0a.
So $arr[0] would be the array of values that you are looking for.
See example on ideone
Works with multiple 7878 values and multiple 0d0a values (even though that's ridiculous).
Update
If splitting is more your style, why not avoid regular expressions altogether?
<?php
$string = "787817878110d0a22278780d0a78783330d0a";
$arr = explode('0d0a7878', $string);
$string = implode('0d0a,7878', $arr);
$arr = explode(',', $string);
print_r($arr);
?>
Here we split the string by the delimiter 0d0a7878, which is what #CharlieGorichanaz's solution is doing, and props to him for the quick, accurate solution. We then add a comma, because who doesn't love comma separated values? And we explode again on the commas for an array of desired values. Performance-wise, this ought to be faster than using regular expressions. See example.

Remove elements of one array if it is found in another [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Remove item from array if it exists in a 'disallowed words' array
I have a dynamic string that clients will send and I want to create comma delimited tags from it:
$subject = "Warmly little in before cousin as sussex and an entire set Blessing it ladyship.";
print_r($tags = explode(" ", strtolower($subject)));
And yet, I want to delete a specific group of words (such as definite articles), but I want to delete the key and value of that word if it is in the exploded array:
$definite_articles = array('the','this','then','there','from','for','to','as','and','or','is','was','be','can','could','would','isn\'t','wasn\'t', 'until','should','give','has','have','are','some','it','in','if','so','of','on','at','an','who','what','when','where','why','we','been','maybe','further');
If one of these words in the $definite_article array are in the $tags array delete the key and value of that word and the new array will have these words taken out. I will have this array be used by array_rand to have a random group of words chosen out of it. I've tried many things to achieve my result, but nothing so far. Can someone help me find a resolve to this?
You are looking for array_diff:
$subject = "Warmly little in before cousin as sussex...";
$tags = explode(" ", strtolower($subject));
$definite_articles = array('the','this','then','there','from','for','to','as');
$tags = array_diff($tags, $definite_articles);
print_r($tags);
See it in action.
Sounds like an easy job for array_diff().
array array_diff ( array $array1 , array $array2 [, array $... ] )
Compares array1 against array2 and returns the difference.
Which basically means it will return array1 after it's been stripped of all values which exist in array2.

Categories