How can i use (str_word_count($str, 1)); as an array and omit words assigned a number by leaving them out... So Hello [1] => World [2] => This [3] => Is [4] => a [5] => Test ) 6 only outputs the numbers i define, such as [1] and [2] to omit This is a test leaving only leaving Hello World, or [1] and [6] for Hello Test...
You can do that with array_intersect and str_word_count or explode
$input = 'Hello World This Is a Test';
$allow = array('Hello', 'Test');
$data = explode(' ', $input);
// or your way
$data = str_word_count($input, 1);
$output = array_intersect($data, $allow);
$count = count($output);
echo 'Found ' + $count;
var_dump($output);
PHP 5.3 solution
$input = 'Hello World This Is a Test';
$allow = array('Hello', 'World');
$array = array_filter(
str_word_count( $input, 1 ),
function( $v ) use( $allow ) {
return in_array( $v, $allow ) ? $v : false;
}
);
print_r( $array );
Related
From this Array of Words
$words = ['THIS', 'IS', 'AN', 'EXAMPLE'];
I want to make Sentences like the following:
$sentences = [
'THIS IS AN EXAMPLE',
'THIS IS AN',
'THIS IS',
'THIS'
];
Also i would like to know how to reverse the ORDER of it,
Like to start from THIS to EXAMPLE like 'THIS IS AN EXAMPLE'
Or to start from EXAMPLE to THIS like 'EXAMPLE AN IS THIS'
or getting both from Forward to Backward and from Backward to Forward so i get
$sentences = [
'THIS IS AN EXAMPLE',
'THIS IS AN',
'THIS IS',
'THIS',
`EXAMPLE AN IS THIS`,
`EXAMPLE AN IS`,
`EXAMPLE AN`,
`EXAMPLE`
];
What I've tried was
$sentences = [];
$words = ['THIS', 'IS', 'AN', 'EXAMPLE'];
$wordscount = count($words);
$i = 1;
while ($i < $wordscount) {
$newword = '';
foreach ($words as $word) {
$newword .= "$word ";
}
while (in_array($newword, $sentences)) {
$newword = explode(' ', $newword);
$newword = array_pop($newword);
$newword = implode(' ', $newword);
echo "$newword <br>";
}
$sentences[] = $newword;
$i++;
}
print_r($sentences);
and it is incomplete Because when i load the page the Web Browser and FastCGI CPU Usage Jumps to 50% for each one And page shows me Memory Usage Problem.
This is how I would do it:
Create a loop which will iterate the total amount of items in the array.
Reduce the array by the iteration value and implode it into a return
array.
Then do the same again but simply with a reversed array and merge them both.
For example:
<?php
function join_words($words) {
$return = [];
for ($i=0; $i < count($words); $i++) {
$return[] = implode(' ', array_slice($words, 0, $i+1));
}
return $return;
}
$words = ['THIS', 'IS', 'AN', 'EXAMPLE'];
$result = [];
$result = array_merge($result, join_words($words));
$result = array_merge($result, join_words(array_reverse($words)));
print_r($result);
https://3v4l.org/vG7tj
Result:
Array
(
[0] => THIS
[1] => THIS IS
[2] => THIS IS AN
[3] => THIS IS AN EXAMPLE
[4] => EXAMPLE
[5] => EXAMPLE AN
[6] => EXAMPLE AN IS
[7] => EXAMPLE AN IS THIS
)
If you want the exact output as shown, you should reverse the array before merging it.
$result = [];
$result = array_merge($result, array_reverse(join_words($words)));
$result = array_merge($result, array_reverse(join_words(array_reverse($words))));
https://3v4l.org/R4LDo
Result:
Array
(
[0] => THIS IS AN EXAMPLE
[1] => THIS IS AN
[2] => THIS IS
[3] => THIS
[4] => EXAMPLE AN IS THIS
[5] => EXAMPLE AN IS
[6] => EXAMPLE AN
[7] => EXAMPLE
)
I'm trying to create an array in PHP that has the structure defined by a string. It will loop through and use the first value as the value and the second value as the quantity. For instance the 1|3 will have the value of 1, 3 times and then loop to the next in the string.
Here is what I have so far -
<?php
$quantity = 10;
$string = '1|3,2|3';
$overall_types = array( );
$types = explode( ',', $string );
for ( $i = 1; $i <= $quantity; $i++ )
{
$qc = explode( '|', $types[0] );
$overall_types[$i] = $qc[0];
}
echo '<pre>';
print_r ( $overall_types );
echo '</pre>';
and that gets me
Array
(
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 1
[6] => 1
[7] => 1
[8] => 1
[9] => 1
[10] => 1
)
but, I want the result to be
Array
(
[1] => 1
[2] => 1
[3] => 1
[4] => 2
[5] => 2
[6] => 2
[7] => 1
[8] => 1
[9] => 1
[10] => 2
)
I'm not sure how to easily switch between the exploded values.
Thanks.
You're not using the repetition count at all from what I see. Achieving this using a straight-forward approach is tricky and probably not necessary when there's a simpler way to do this.
<?php
function buildReps($string) {
$array = [];
$overall_types = array( );
$types = explode( ',', $string );
foreach ($types as $type) {
$qc = explode( '|', $type );
$array = array_merge($array, array_fill(0, $qc[1], $qc[0]));
}
return $array;
}
function buildAllReps($string, $quantity) {
$array = [];
while (count($array) < $quantity) {
$array = array_merge($array, buildReps($string));
}
return array_slice($array, 0, $quantity);
}
$quantity = 10;
$string = '1|3,2|3';
echo '<pre>';
print_r ( buildAllReps($string, $quantity) );
echo '</pre>';
The first function builds the array once based on the $string defintion. The second one just merges the results from the first one until you reach quantity and then stops and returns the correct quantity of items back.
The above outputs:
Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 2
[4] => 2
[5] => 2
[6] => 1
[7] => 1
[8] => 1
[9] => 2
)
Example in https://eval.in/629556
Beware of infinite loops which may occur if the definition supplied by $string does not produce a non-empty array.
There's a better way to do string to array in PHP.
You can use either serialize and unserialize or json_encode and json_decode to create strings and then to convert them to array. This is far better than what you would want to implement, because those methods are in the php core, which means they are faster.
http://php.net/serialize
http://php.net/manual/ro/function.json-encode.php
From json string to array, you will need to do something like this:
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
// extra boolean parameter set to true to return array instead of json object
$array = json_decode($json, true);
<?php
$quantity = 10;
$string = '1|3,2|3';
$overall_types = [];
$types = explode( ',', $string );
for($c = 0; $c < $quantity; $c++) {
foreach ($types as $currentType) {
$qc = explode( '|', $currentType );
for ($i = 0; $i < $qc[1]; $i++) {
$overall_types[] = $qc[0];
}
}
}
$overall_types = array_slice($overall_types,0,$quantity);
echo '<pre>';
print_r ( $overall_types );
echo '</pre>';
This should give you the output that you need.
Not going into micro benchmarking here but you could probably also preg_replace /g the \w|\d+, multipliers by their full string representation and only preg_split the entire string into an array after this step. Like so:
$string = '1|3,2|3';
print_r(str_split(preg_replace_callback('/(\w)\|(\d+),?/', function($a) {
return str_repeat($a[1], $a[2]);
}, $string)));
Less array handling and potentially faster.
I would however suggest to reconsider the initial string representation and look for a better approach. Why is this format needed if it needs to be converted anyway?
I have an export from a legacy system which i want to import into an RDBMS solution.
The export file has data as the example below
%a = (
'1' => 'test',
'3' => 'test2',
'44' => 'this is another test()
);
%b = (
'1' => 'super man'
);
%c = (
'username' => 'testing'
);
I wish to get these files into associative php array so that i can iterate into the database table, check if the values exist and save it if it does not exist.
I am stuck with the parsing of the file part.
so far i have been able to reach here
$string = file_get_contents($path);
$params = explode("%", $string); // to separate the main chunks
foreach ($params as $keyvalue) {
if ($keyvalue!='') { //as the file starts with % to truncate the first blank result
$trimmed=substr(trim($keyvalue, ' '), 3, strlen($keyvalue) - 4); // remove this part from the result 'a='
$finalArray = explode(";", $trimmed); // remove the semi column
$array = $finalArray[0];
print_r($array );
echo '<br/>';
echo '<br/>';
echo '<br/>';
echo '<br/>';
}
with the above i do get this output
( "1" => "test", "3" => "test2" ,'44' => 'this is another test())
( '1' => 'super man' )
('username' => 'testing' )
displayed on different lines, i tried json_decode (...,true), unserialise ect to convert this output into array so that i can loop with no success.
Any help will be most welcomed.
try this
$array[] = $finalArray[0];
Because you creating new array everytime. You need to append to the existing array so as to get the desired output.
And my edited code is below
$params = explode("%", $string);
$i = 0;
foreach ($params as $keyvalue) {
if ($keyvalue!='') {
$trimmed=substr(trim($keyvalue, ' '), 3, strlen($keyvalue) - 4);
$finalArray = explode(";", $trimmed);
$array = $finalArray[0];
$newArray = explode(',',substr($array, 1, -1));
foreach($newArray as $arravalue) {
$newArray1 = explode('=>',substr($arravalue, 1, -1));
$finalResultArray[$i][trim(str_replace("'","",$newArray1[0]))] = '"'.trim(str_replace("'","",$newArray1[1])).'"';
}
$i++;
}
}
It gives an output array $finalResultArray with the below format.
Array
(
[0] => Array
(
[1] => "test"
[3] => "test2"
[44] => "this is another test("
)
[1] => Array
(
[1] => "super man"
)
[2] => Array
(
[username] => "testing"
)
)
I made a little tweek with string replace to do the trick, by converting it to a json format replacing the ( by { the => by : and ) by }
it seem to work fine but if there is a neater solution I would like to welcome it.
$string = file_get_contents($path);
$params = explode("%", $string);
foreach ($params as $keyvalue) {
if ($keyvalue!='') {
$trimmed=substr(trim($keyvalue, ' '), 3, strlen($keyvalue) - 4);
$finalArray = explode(";", $trimmed);
$array = $finalArray[0];
print_r($array); // display 1
$string2 = str_replace('(', '{', $array);
$string3 = str_replace(')', '}', $string2);
$string4 = str_replace('=>', ':', $string3);
$ar = json_decode($string4);
echo ('<pre>');
//echo $first; // value
print_r( $ar);
echo('</pre>'); //display 2
die('wa');
echo '<br/>';
echo '<br/>';
echo '<br/>';
echo '<br/>';
}
}
//display 1
( "1" => "test1", "2" => "test2", "3" => "test4")
display 2
stdClass Object
(
[1] => test1
[2] => test2
[3] => test4
)
$str = "This is a string";
$words = explode(" ", $str);
Works fine, but spaces still go into array:
$words === array ('This', 'is', 'a', '', '', '', 'string');//true
I would prefer to have words only with no spaces and keep the information about the number of spaces separate.
$words === array ('This', 'is', 'a', 'string');//true
$spaces === array(1,1,4);//true
Just added: (1, 1, 4) means one space after the first word, one space after the second word and 4 spaces after the third word.
Is there any way to do it fast?
Thank you.
For splitting the String into an array, you should use preg_split:
$string = 'This is a string';
$data = preg_split('/\s+/', $string);
Your second part (counting spaces):
$string = 'This is a string';
preg_match_all('/\s+/', $string, $matches);
$result = array_map('strlen', $matches[0]);// [1, 1, 4]
Here is one way, splitting the string and running a regex once, then parsing the results to see which segments were captured as the split (and therefore only whitespace), or which ones are words:
$temp = preg_split('/(\s+)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$spaces = array();
$words = array_reduce( $temp, function( &$result, $item) use ( &$spaces) {
if( strlen( trim( $item)) === 0) {
$spaces[] = strlen( $item);
} else {
$result[] = $item;
}
return $result;
}, array());
You can see from this demo that $words is:
Array
(
[0] => This
[1] => is
[2] => a
[3] => string
)
And $spaces is:
Array
(
[0] => 1
[1] => 1
[2] => 4
)
You can use preg_split() for the first array:
$str = 'This is a string';
$words = preg_split('#\s+#', $str);
And preg_match_all() for the $spaces array:
preg_match_all('#\s+#', $str, $m);
$spaces = array_map('strlen', $m[0]);
Another way to do it would be using foreach loop.
$str = "This is a string";
$words = explode(" ", $str);
$spaces=array();
$others=array();
foreach($words as $word)
{
if($word==' ')
{
array_push($spaces,$word);
}
else
{
array_push($others,$word);
}
}
Here are the results of performance tests:
$str = "This is a string";
var_dump(time());
for ($i=1;$i<100000;$i++){
//Alma Do Mundo - the winner
$rgData = preg_split('/\s+/', $str);
preg_match_all('/\s+/', $str, $rgMatches);
$rgResult = array_map('strlen', $rgMatches[0]);// [1,1,4]
}
print_r($rgData); print_r( $rgResult);
var_dump(time());
for ($i=1;$i<100000;$i++){
//nickb
$temp = preg_split('/(\s+)/', $str, -1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$spaces = array();
$words = array_reduce( $temp, function( &$result, $item) use ( &$spaces) {
if( strlen( trim( $item)) === 0) {
$spaces[] = strlen( $item);
} else {
$result[] = $item;
}
return $result;
}, array());
}
print_r( $words); print_r( $spaces);
var_dump(time());
int(1378392870)
Array
(
[0] => This
[1] => is
[2] => a
[3] => string
)
Array
(
[0] => 1
[1] => 1
[2] => 4
)
int(1378392871)
Array
(
[0] => This
[1] => is
[2] => a
[3] => string
)
Array
(
[0] => 1
[1] => 1
[2] => 4
)
int(1378392873)
$financialYear = 2015-2016;
$test = explode('-',$financialYear);
echo $test[0]; // 2015
echo $test[1]; // 2016
Splitting with regex has been demonstrated well by earlier answers, but I think this is a perfect case for calling ctype_space() to determine which result array should receive the encountered value.
Code: (Demo)
$string = "This is a string";
$words = [];
$spaces = [];
foreach (preg_split('~( +)~', $string, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $s) {
if (ctype_space($s)) {
$spaces[] = strlen($s);
} else {
$words[] = $s;
}
}
var_export([
'words' => $words,
'spaces' => $spaces
]);
Output:
array (
'words' =>
array (
0 => 'This',
1 => 'is',
2 => 'a',
3 => 'string',
),
'spaces' =>
array (
0 => 1,
1 => 1,
2 => 4,
),
)
If you want to replace the piped constants used by preg_split() you can just use 3 (Demo). This represents PREG_SPLIT_NO_EMPTY which is 1 plus PREG_SPLIT_DELIM_CAPTURE which is 2. Be aware that with this reduction in code width, you also lose code readability.
preg_split('~( +)~', $string, -1, 3)
What about this? Does someone care to profile this?
$str = str_replace(["\t", "\r", "\r", "\0", "\v"], ' ', $str); // \v -> vertical space, see trim()
$words = explode(' ', $str);
$words = array_filter($words); // there would be lots elements from lots of spaces so skip them.
I previously had some help with this matter from #HSZ but have had trouble getting the solution to work with an existing array. What im trying to do is explode quotes, make all words uppercase plus get each words index value and only echo the ones i define then implode. In simplest terms, always remove the 4th word within quotations or the 3rd and 4th... This could probably done with regex as well.
Example:
Hello [1] => World [2] => This [3] => Is [4] => a [5] => Test ) 6 only outputs the numbers i define, such as 1 - (Hello) and [2] - (World) leaving out [3], [4], [5] and [6] or This is a test leaving only Hello World, or 1 and [6] for Hello Test...
Such as:
echo $data[1] + ' ' + $data[6]; //Would output index 1 and 6 Hello and Test
Existing Code
if (stripos($data, 'test') !== false) {
$arr = explode('"', $data);
for ($i = 1; $i < count($arr); $i += 2) {
$arr[$i] = strtoupper($arr[$i]);
$arr[$i] = str_word_count($arr, 1); // Doesnt work with array of course.
}
$arr = $matches[1] + ' ' + $matches[6];
$data = implode('"', $arr);
}
Assuming $data is 'Hello world "this is a test"', $arr = explode('"', $data) will be the same as:
$arr = array (
[0] => 'Hello World',
[1] => 'This is a test'
)
If you want to do things with this is a test, you can explode it out using something like $testarr = explode(' ', $arr[1]);.
You can then do something like:
$matches = array();
foreach ($testarr as $key => $value) {
$value = strtoupper($value);
if(($key+1)%4 == 0) { // % is modulus; the result is the remainder the division of two numbers. If it's 0, the key+1 (compensate for 0 based keys) is divisible by 4.
$matches[] = $value;
}
}
$matches = implode('"',$matches);