I'm not very familiar with php and got stuck in how to use substr in this case:
I have to do the parse of a string that has some numbers and symbols,
example:
1[2[3,5],4[7[65,9,11],8]]
And to do this I used a for that will go through and get each char of the string,
something like that:
$count = 0;
for($i = 0; $i <= strlen($string); $i++){
$char = substr($string, $i, 1);
if($char == '['){
$count --;
}
if($char == ']'){
$count ++;
}
if($count == 0){
break;
}
if(is_numeric(substr($string, $i +1, 1)) and $count == -1){
$number = substr($string, $i +1, 1);
$array_aux[] = $number;
}
}
But as I'm getting the char in (substr ($ string, $ i, 1)) it does not work for numbers with more than one digit, such as 65 and 11
And the contents of the array gets something like: (..., 6, 5, 9, 1, 1, ...)
When should be something like: (..., 65, 9, 11, ...)
Any help?
Sorry, I think was not clear enough.
I need the numbers that are inside '[' when count has the value -1
(that's why I'm using substr, and taking every char)
examples: when the string is: 1[2[3,5],4[7[65,9,11],8]], the array must contain 2 and 4
when the string is: 2[3,5],4[7[65,9,11],8]], the array must contain 3 and 5
when the string is: 7[65,9,11],8]], the array must contain 65, 9 and 11. And so on...
Sorry to put these details only now, I was without computer :(
preg_match_all with a simple regular expression can do this for you:
$in = "1[2[3,5],4[7[65,9,11],8]]";
preg_match_all('~\d+~', $in, $out);
print_r($out[0]);
Outputs:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 4
[5] => 7
[6] => 65
[7] => 9
[8] => 11
[9] => 8
)
You can use preg_split and split by matching one or more times not a digit \D+
$str = "1[2[3,5],4[7[65,9,11],8]]";
print_r(preg_split("/\D+/", $str, -1, PREG_SPLIT_NO_EMPTY));
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 4
[5] => 7
[6] => 65
[7] => 9
[8] => 11
[9] => 8
)
Related
There's a certain contents (from a webpage) where I need to get two numbers of a certain list.
Basically the list goes like:
..... 10 from 12....
..... 1 from 20....
..... 20 from 100...
and so on. For me, I need to get these numbers surrounding the word "from", so I can perform certain calculations with them later.
I looked into this and tried different ways to perform it with strpos or strstr but nothing worked. Does anyone have any idea how to accomplish something like that?
$text = "..... 10 from 12 etc....
..... 1 from 20....
..... 20 from 100...";
$r = preg_match_all('~(\d+) *from *(\d+)~u',$text,$match, PREG_SET_ORDER);
var_export($match);
Output:
array (
0 =>
array (
0 => '10 from 12',
1 => '10',
2 => '12',
),
1 =>
array (
0 => '1 from 20',
1 => '1',
2 => '20',
),
2 =>
array (
0 => '20 from 100',
1 => '20',
2 => '100',
),
)
Explanations:
\d+ one digit or more
(\d+) the sequence in brackets -> the digits in the result array
* no, one or more spaces
from the word from
Here is an example of what you can do with explode:
<?php
/* the text with many different gaps and mess! */
$text = "wlfsdjf;sd sdfljsdfk kfgjdlg d 10 from 200 kflgjdkgdklgsd slfksjd
dfgdf fgdlkjdf d 20 from 30 ldk;lfsd
dflksdjf 40 from 50 dkf;sd sdjfs ";
/* main array */
$array = explode("\n",$text);
echo '<pre>';
print_r($array);
/* looping and clearing out our values per line */
foreach($array as $k => $line){
$f = explode(" ",explode(" from ",$line)[0]);
$f = array_pop($f);
$numbers[$k]['first'] = $f;
$s = explode(" ",explode(" from ",$line)[1]);
$s = $s[0];
$numbers[$k]['second'] = $s;
}
/* our new array set per line */
print_r($numbers);
Will return:
Array
(
[0] => wlfsdjf;sd sdfljsdfk kfgjdlg d 10 from 200 kflgjdkgdklgsd slfksjd
[1] => dfgdf fgdlkjdf d 20 from 30 ldk;lfsd
[2] => dflksdjf 40 from 50 dkf;sd sdjfs
)
Array
(
[0] => Array
(
[first] => 10
[second] => 200
)
[1] => Array
(
[first] => 20
[second] => 30
)
[2] => Array
(
[first] => 40
[second] => 50
)
)
I have an array of 20 different numbers which contains ranking of students.
I want to split this array into two sub arrays of equal length i.e 10
I also want the sum of all numbers within each array to be close.
For example, in sub-array A there could be a total sum of 56 and in sub-array B there could be a total sum of 57.
I am using PHP.
I sort the main array here and would like to assign index[0] to sub-array A and index[1] to sub-array B, and keep repeating this until both arrays are filled.
My approach works but i think its not great and not dynamic.
I interate through the main original array for [i] and then add that to the first sub-array, then I set i = i+2 so that I get every second value and store them in the first array.
I then remove the value at index[i] from the main array.
What is left over is now sub-array B.
$kids = array (8,5,6,9,3,8,2,4,6,10,8,5,6,1,7,10,5,3,7,6);
sort($kids);
$arrlength = count($kids);
for($x = 0; $x < $arrlength; $x++) {
echo $kids[$x];
echo "<br>";
}
$teamA = array();
$teamB = array();
$i = 0;
while ($i < $arrlength)
{
#echo $kids[$i] ."<br />";
array_push($teamA, $kids[$i]);
unset($kids[$i]);
$i += 2;
}
$teamB = $kids;
print_r($teamA);
print_r($teamB);
My Output is :
Array ( [0] => 1 [1] => 3 [2] => 4 [3] => 5 [4] => 6 [5] => 6 [6] => 7 [7] =>
8 [8] => 8 [9] => 10 )
The sum here of all values is = 58
Array ( [1] => 2 [3] => 3 [5] => 5 [7] => 5 [9] => 6
[11] => 6 [13] => 7 [15] => 8 [17] => 9 [19] => 10 )
The sum here of all values is = 61
Any help is greatly appreciated. I have no real experience with PHP or its built in functions so sorry if this is a basic question. Thanks!
There is a built-in helper function of php, array_slice. You can read about it in the link I provided.
Here's how you can use in to achieve what you want:
$kids = array (5,7,6,8,3,8,2,4,6,10,8,5,6,10,7,6,5,3,7,6);
sort($kids);
$arrlength = count($kids);
$arrayA= array_slice($kids, 0, $arrlength / 2);
$arrayB= array_slice($kids, $arrlength / 2);
Output
// $arrayA
array:10 [▼
0 => 2
1 => 3
2 => 3
3 => 4
4 => 5
5 => 5
6 => 5
7 => 6
8 => 6
9 => 6
]
// $arrayB
array:10 [▼
0 => 6
1 => 6
2 => 7
3 => 7
4 => 7
5 => 8
6 => 8
7 => 8
8 => 10
9 => 10
]
Another approach for achieving what you asked
$kids = array(8,5,6,9,3,8,2,4,6,10,8,5,6,1,7,10,5,3,7,6);
sort($kids);
$teamA = array();
$teamB = array();
foreach($kids as $i => $kid){
if($i % 2){
array_push($teamA, $kid);
} else{
array_push($teamB, $kid);
}
}
It will generate the same output and sum as you want.
Hello guys I have a small question that suppose I have a string as
"Hello My name is XYZ"
Now I know I can find the length of the words as "Hello" has 5 characters and "My" has 2 characters. By using following code
$text = file_get_contents('text.txt'); // $text = 'Hello my name is XYZ';
$words = str_word_count($text, 1);
$wordsLength = array_map(
function($word) { return mb_strlen($word, 'UTF-8'); },
$words
);
var_dump(array_combine($words, $wordsLength));
But what if i want to find that the number of words with length 1 is 0. The number of words with lengths 2 is 2. The number of words with length 3 is 1 and so on till number of length 10
Note- I am considering the word length till there is a space Suppose there is a date in the data like 20.04.2016 so it should show me that the number is words with length 10 is 1.
and one more thing how do I find the average length for the words in the string.
Thank you in advance
If you use array_count_values() on the $wordsLength array it will give a count of the string lengths there are. If you use this and a template array (created using array_fill()) with the elements 1-10 and a value of 0. You will get a list of all of the word counts...
$counts = array_replace(array_fill(1, 9, 0),
array_count_values($wordsLength));
will give...
Array
(
[1] => 0
[2] => 2
[3] => 1
[4] => 1
[5] => 1
[6] => 0
[7] => 0
[8] => 0
[9] => 0
)
Hi try this it works on the date and special chars,emojis
$text = 'Hello 20.04.2016 🚩 my face😘face is XYZ';
$words =preg_split('/\s+/', $text);
$wordsLength = array_map(
function($word) { return mb_strlen($word, 'UTF-8'); } ,$words);
print_r($words);
//Get Average word Length
$avg=round(array_sum($wordsLength)/count($words),1);
//print Avg
print($avg);
?>
(Demo)
$text = ' Hello 20.04.2016 🚩 my incredibleness face😘face is XYZ ';
Generate array of continuous visible characters
$words = preg_split('/\s+/', $text, 0, PREG_SPLIT_NO_EMPTY);
array (
0 => 'Hello',
1 => '20.04.2016',
2 => '🚩',
3 => 'my',
4 => 'incredibleness',
5 => 'face😘face',
6 => 'is',
7 => 'XYZ',
)
Replace visible strings with their multibyte length notice the simpler syntax
$wordsLength = array_map('mb_strlen', $words);
array (
0 => 5,
1 => 10,
2 => 1,
3 => 2,
4 => 14,
5 => 9,
6 => 2,
7 => 3,
)
Group and count lengths
$lengthCounts = array_count_values($wordsLength);
array (
5 => 1,
10 => 1,
1 => 1,
2 => 2,
14 => 1,
9 => 1,
3 => 1,
)
Establish an array of defaults, because $lengthCounts may have gaps
$defaultCounts = array_fill_keys(range(1,10), 0);
array (
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
)
Filter the counts to remove elements/counts that are out-of-range
$filteredCounts = array_intersect_key($lengthCounts, $defaultCounts);
array (
5 => 1,
10 => 1,
1 => 1,
2 => 2,
9 => 1,
3 => 1,
)
Overwrite the defaults with found counts to prevent gaps in the output
$gaplessCounts = array_replace($defaultCounts, $filteredCounts);
array (
1 => 1,
2 => 2,
3 => 1,
4 => 0,
5 => 1,
6 => 0,
7 => 0,
8 => 0,
9 => 1,
10 => 1,
)
$line = "Type:Bid, End Time: 12/20/2018 08:10 AM (PST), Price: $8,000,Bids: 14, Age: 0, Description: , Views: 120270, Valuation: $10,75, IsTrue: false";
I need to get this array:
Array ( [0] => Bid [1] => 12/20/2018 08:10 AM (PST) [2] => $8,000 [3] => 14 [4] => 0 [5] => [6] => 120270 [7] => $10,75 [8] => false )
I agree with Andreas about using preg_match_all(), but not with his pattern.
For stability, I recommend consuming the entire string from the beginning.
Match the label and its trailing colon. [^:]+:
Match zero or more spaces. \s*
Forget what you matched so far \K
Lazily match zero or more characters (giving back when possible -- make minimal match). .*?
"Look Ahead" and demand that the matched characters from #4 are immediately followed by a comma, then 1 or more non-comma&non-colon character (the next label), then a colon ,[^,:]+: OR the end of the string $.
Code: (Demo)
$line = "Type:Bid, End Time: 12/20/2018 08:10 AM (PST), Price: $8,000,Bids: 14, Age: 0, Description: , Views: 120270, Valuation: $10,75, IsTrue: false";
var_export(
preg_match_all(
'/[^:]+:\s*\K.*?(?=\s*(?:$|,[^,:]+:))/',
$line,
$out
)
? $out[0] // isolate fullstring matches
: [] // no matches
);
Output:
array (
0 => 'Bid',
1 => '12/20/2018 08:10 AM (PST)',
2 => '$8,000',
3 => '14',
4 => '0',
5 => '',
6 => '120270',
7 => '$10,75',
8 => 'false',
)
New answer according to new request:
I use he same regex for spliting the string and I replace after what is before the colon:
$line = "Type:Bid, End Time: 12/20/2018 08:10 AM (PST), Price: $8,000,Bids: 14, Age: 0, Description: , Views: 120270, Valuation: $10,75, IsTrue: false";
$parts = preg_split("/(?<!\d),|,(?!\d)/", $line);
$result = array();
foreach($parts as $elem) {
$result[] = preg_replace('/^[^:]+:\h*/', '', $elem);
}
print_r ($result);
Output:
Array
(
[0] => Bid
[1] => 12/20/2018 08:10 AM (PST)
[2] => $8,000
[3] => 14
[4] => 0
[5] =>
[6] => 120270
[7] => $10,75
[8] => false
)
I'd use preg_match instead.
Here the pattern looks for digit(s) comma digit(s) or just digit(s) or a word and a comma.
I append a comma to the string to make the regex simpler.
$line = "TRUE,59,m,10,500";
preg_match_all("/(\d+,\d+|\d+|\w+),/", $line . ",", $match);
var_dump($match);
https://3v4l.org/HQMgu
Even with a different order of the items this code will still produce a correct output: https://3v4l.org/SRJOf
much bettter idea:
$parts=explode(',',$line,4); //explode has a limit you can use in this case 4
same result less code.
I would keep it simple and do this
$line = "TRUE,59,m,10,500";
$parts = preg_split("/,/", $line);
//print_r ($parts);
$parts[3]=$parts[3].','.$parts[4]; //create a new part 3 from 3 and 4
//$parts[3].=','.$parts[4]; //alternative syntax to the above
unset($parts[4]);//remove old part 4
print_r ($parts);
i would also just use explode(), rather than a regular expression.
I have this small problem although it's small i can't seem to work it out, I've set of data i need to display, lets say 1 to 17. i need to display 3 in a row like 1,2,3 in one row and 4,5,6 in the next because bootstrap row support 12 columns and there are 3 elements of 4 columns each.
Because the amount of data can vary and the total number of data won't divide by 3 like the example it's 17 how can I write something in PHP that will display the data 3 in a row and like in this example there will be 5 rows of 3 and a last row having 2 sets.
Thanks
Edit:
I didn't write any code of this but was thinking a loop and a nested loop but think that's too clunky any better way of doing this?
You can use following code :
for($i = 1;$i<=17;$i++){
if($i%3 !=1 && $i%3 != 0){
print_r($i." , ");
}else if( $i%3 == 0){
print_r($i);
}
else{
print_r("<br/>".$i." , ");
}
}
It'll give you output like this:
1 , 2 , 3
4 , 5 , 6
7 , 8 , 9
10 , 11 , 12
13 , 14 , 15
16 , 17 ,
Rukshan you can use the modulus operator.
You can use the code below as an example. I have mixed html and php, but it is just to show you an example:--
<?php
echo "<table>";
for($i=1;$i<18;$i++)
{
echo "<tr>";
echo "<td>".$i."</td>";
if($i%3 == 0) echo "</tr>";
}
echo "</table>";
?>
Try using array_slice() to slice your array as per your need. You will get your division in arrays. Loop through them to create your table.
Reference Example
$stores = array(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12);
$division = ceil( count($stores) / 3 ); //to divide array into 3 halves
$firstHalf = array_slice($stores, 0, $division);
$secondHalf = array_slice($stores, $division, $division);
$thirdHalf = array_slice($stores, $division * 2);
Output for $stores = array(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Array
(
[0] => 5
[1] => 6
[2] => 7
[3] => 8
)
Array
(
[0] => 10
[1] => 11
[2] => 12
)
Output for $stores = array(1, 2, 3, 4, 5, 6, 7, 8, 10)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Array
(
[0] => 5
[1] => 6
[2] => 7
[3] => 8
)
Array
(
[0] => 9
[1] => 10
)
Output for $stores = array(1, 2, 3, 4, 5, 6, 7, 8);
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 4
[1] => 5
[2] => 6
)
Array
(
[0] => 7
[1] => 8
)
To divide the array in two halves you can use
$division = ceil( count($stores) / 2 );
$firstHalf = array_slice($stores, 0, $division);
$secondHalf = array_slice($stores, $division);