I have a plain string like this:
1 //here is a number defines phrase name
09/25/2013 //here is a date
<i>some text goes here</i> //and goes text
2
09/24/2013
text goes on and on
4 //as you can see, the numbers can skip another
09/23/2013
heya i'm a text
I need to create array from this but the numbers that defines phrases must give me the date of that line and return the text when i called it. Like,
$line[4][date] should give me "09/23/2013"
Is that possible, if possible can you explain me how to do this?
$stringExample = "1
09/25/2013
<i>some text goes here</i>
2
09/24/2013
text goes on and on
and on and on
4
09/23/2013
heya i'm a text";
$data = explode("\r\n\r\n", $stringExample);
$line = array();
foreach ($data as $block) {
list($id, $date, $text) = explode("\n", $block, 3);
$index = (int) $id;
$line[$index] = array();
$line[$index]["date"] = trim($date);
$line[$index]["text"] = trim($text);
}
var_dump($line) should output:
array(3) {
[1]=>
array(2) {
["date"]=>
string(10) "09/25/2013"
["text"]=>
string(26) "<i>some text goes here</i>"
}
[2]=>
array(2) {
["date"]=>
string(10) "09/24/2013"
["text"]=>
string(34) "text goes on and on
and on and on"
}
[4]=>
array(2) {
["date"]=>
string(10) "09/23/2013"
["text"]=>
string(15) "heya i'm a text"
}
}
You can test it here.
If the structure of the file is a coerent pattern of rows, with PHP you read each line and each 1st you have the number, each 2nd you have the date, each 3rd you have the text, each 4th you have empty, you reset the counter to 1 and go on like that, and put values in arrays, using even an external index, or the 1st line (number) as index.
try this:
EDIT: should now work for multi line text.
//convert the string into an array at newline.
$str_array = explode("\n", $str);
//remove empty lines.
foreach ($str_array as $key => $val) {
if ($val == "") {
unset($str_array[$key]);
}
}
$str_array = array_values($str_array);
$parsed_array = array();
$count = count($str_array);
$in_block = false;
$block_num = 0;
$date_pattern = "%[\d]{2}/[\d]{2}/[\d]{2,4}%";
for ($i = 0; $i < $count; $i++) {
//start the block at first numeric value.
if (isset($str_array[$i])
&& is_numeric(trim($str_array[$i]))) {
// make sure it's followed by a date value
if (isset($str_array[$i + 1])
&& preg_match($date_pattern, trim($str_array[$i + 1]))) {
//number, followed by date, block confirmed.
$in_block = true;
$block_num = $i;
$parsed_array[$str_array[$i]]["date"] = $str_array[$i + 1];
$parsed_array[$str_array[$i]]['text'] = "";
$i = $i + 2;
}
}
//once a block has been found, everything that
//is not "number followed by date" will be appended to the current block's text.
if ($in_block && isset($str_array[$i])) {
$parsed_array[$str_array[$block_num]]['text'].=$str_array[$i] . "\n";
}
}
var_dump($parsed_array);
Related
i want to make a php loop that puts the values from a string in 2 different variables.
I am a beginner. the numbers are always the same like "3":"6" but the length and the amount of numbers (always even). it can also be "23":"673",4:6.
You can strip characters other than numbers and delimiters, and then do explode to get an array of values.
$string = '"23":"673",4:6';
$string = preg_replace('/[^\d\:\,]/', '', $string);
$pairs = explode(',', $string);
$pairs_array = [];
foreach ($pairs as $pair) {
$pairs_array[] = explode(':', $pair);
}
var_dump($pairs_array);
This gives you:
array(2) {
[0]=>
array(2) {
[0]=>
string(2) "23"
[1]=>
string(3) "673"
}
[1]=>
array(2) {
[0]=>
string(1) "4"
[1]=>
string(1) "6"
}
}
<?php
$string = '"23":"673",4:6';
//Remove quotes from string
$string = str_replace('"','',$string);
//Split sring via comma (,)
$splited_number_list = explode(',',$string);
//Loop first list
foreach($splited_number_list as $numbers){
//Split numbers via colon
$splited_numbers = explode(':',$numbers);
//Numbers in to variable
$number1 = $splited_numbers[0];
$number2 = $splited_numbers[1];
echo $number1." - ".$number2 . "<br>";
}
?>
I have this array
array(6) {
[0]=>
string(7) "1234567"
[1]=>
string(5) "7548#"
[2]=>
string(9) "1254#abc#"
[3]=>
string(5) "32514"
[4]=>
string(6) "2548##"
[5]=>
string(5) "3258#"
}
I want to validate this data based on provided condition.
If ID(array[0] and array[3] or array[n]) is an integer check the *data* which is(array[1] and array[4] or array[n]) and if that data not contain more then one #, return false;
here is my sample code, but I'm only able to check the first and 2nd array,
if(preg_match('/^[1-7]{1,7}$/', current($arr))){
next($arr);
if(substr_count(next($arr),"#") <=1)
//false
else
echo "true";
}
help needed, thanks.
You can use a for loop, which allows you to control the start point, the condition when to stop and the step your using, so...
$arr = ["1234567", "7548#", "1254#abc#", "32514", "2548##", "3258#"];
for ( $i = 0; $i < count($arr); $i+=3) {
echo $arr[$i].PHP_EOL;
if ( preg_match('/^[1-7]{1,7}$/', $arr[$i]) ) {
if(substr_count($arr[$i+1],"#") > 1) { // Check if it's +1 or +2 here
echo "true".PHP_EOL;
}
else {
echo "false".PHP_EOL;
}
}
}
This loops from the start to the number of elements in your source, but just every 3rd item.
The rest uses similar code to what you've already got, but using the array elements relative to the loop counter ($arr[$i+1] for example). You will have to check if this is the right element you want to check as it may be $arr[$i+2], but the concept is the same.
This outputs..
1234567
false
32514
true
One thing I would recommend is to try and write if statements so that you always get something from it being 'true'. In your code you use <=1 and then there is nothing to do - if you change that round to >1, then it means you can get rid of the 'empty' statement.
you need to create a loop then you can write your rules for specific n.
$n = 3; //Your modulo
for($x = 0, $l = count($array); $x < $l; $x++ ) { //$array is your array
if($x % $n == 0) {
$result = preg_match('/^[1-7]{1,7}$/',$array[$x]);
} else if ($x % $n == 1) {
$result = substr_count($array[$x], '#') > 1;
} else {
$result = true; //no specific rule
}
if(!$result) { //if validation fails
echo "Validation failed";
break;
}
}
I would like to manipulate array elements. So if a certain array element ends with the letter n or m and the following element is for example apple then I want to delete the "a" of "apple" so that I get as an output: Array ( [0] => man [1] => pple )
My Code:
$input = array("man","apple");
$ending = array("m","n");
$example = array("apple","orange");
for($i=0;$i<count($input);$i++)
{
$second = isset( $input[$i+1])?$input[$i+1][0]:null;
$third = substr($input[$i],-2);
if( isset($third) && isset($second) ){
if ( in_array($third,$ending) && in_array($second,$example) ){
$input[$i+1] = substr($input[$i+1],0,-2);
}
}
}
How do I have to change my code so that I get the desired output?
Sounds like a cool exercise task.
My approach to this after reading the starting comments would be something like this:
$input = ['man', 'hamster', 'apple', 'ham', 'red'];
$endings = ['m', 'n'];
$shouldRemove = false;
foreach ($input as $key => $word) {
// if this variable is true, it will remove the first character of the current word.
if ($shouldRemove === true) {
$input[$key] = substr($word, 1);
}
// we reset the flag
$shouldRemove = false;
// getting the last character from current word
$lastCharacterForCurrentWord = $word[strlen($word) - 1];
if (in_array($lastCharacterForCurrentWord, $endings)) {
// if the last character of the word is one of the flagged characters,
// we set the flag to true, so that in the next word, we will remove
// the first character.
$shouldRemove = true;
}
}
var_dump($input);
die();
The output of this script would be
array(5) { [0]=> string(3) "man" [1]=> string(6) "amster" [2]=> string(5) "apple" [3]=> string(3) "ham" [4]=> string(2) "ed" }
I hope the explanation with the comments is enough.
I have a database with multiple records. It is structured like this:
["data"]=>
array(5) {
[1]=>
[2]=>
array(11) {
[0]=>
string(1) "0"
[1]=>
string(8) "25000000"
[2]=>
string(3) "day"
[3]=>
string(5) "0.00%"
[4]=>
string(9) "404049904"
[5]=>
string(1) "0"
[6]=>
string(5) "0.00%"
[7]=>
string(1) "0"
[8]=>
string(1) "0"
[9]=>
string(1) "0"
[10]=>
string(3) "0.0"
}
I need to fetch the 8th record and I do this by using
public static function($data)
{
$array = [];
$path = $data->data[2];
foreach($path as $key => $item)
if($key > 1)
{
$array[] = [$item->data[8]];
}
return json_encode($array);
}
This foreach takes all the 8th values from the array but I need to display a single number which is the average of all the 8th values. How can I do this?
Once you've got your array containing all your data, simple sum the array and then divide by the size of the array.. something along these lines
$average = (array_sum($array) / count($array));
Of course you may want to check for count($array) being 0;
Because you put your value into a new array, you can not use array_sum to sum the values, so you should store it.
$sum = 0;
foreach($path as $key => $item)
if($key > 1) {
$array[] = [$item->data[8]];
$sum += $item->data[8];
}
}
$avg = ($sum / count($array); //the average
var_dump($avg);
If is it possible, just put it as a value:
$array[] = $item->data[8]; //no wrapping []
In this case, you can use $avg = array_sum($array) / count($array);
if (count($array)>0){
$avg = array_sum($array) / count($array);
}
I would personally do those calculations in the database before the data gets to your PHP script itself. See AVG().
If you can't for some reason use that I would output those values into a flat array and then just calculate the average. So something like :
function getAverage($data) {
$flatArray = array();
foreach ($data as $row) {
if (!empty($row->8)) {
$flatArray[] = $row->8;
}
}
return (array_sum($flatArray)/count($flatArray));
}
EDIT: Moved to Object traversing on the data row, sorry, missed that initially and thought it was an array in all the nests.
Since you have a loop within your static Method; why not do the calculation therein and return it or add it to the JSON Data if You need your Data in JSON Format? Here's what's implied by the above:
public static function getAverageSum($data) {
$array = [];
$path = $data->data[2];
$sumTotal = 0.00; //<== YOU COULD JUST SUM IT DIRECTLY WITHOUT USING AN ARRAY
foreach($path as $key => $item) {
if ($key > 1) {
$array[] = $item->data[8];
$sumTotal += floatval($item->data[8]);
}
}
// IF YOU ARE ONLY INTERESTED IN THE AVERAGE SUM YOU COULD EVEN ADD IT IT TO THE $array AS AN EXTRA KEY
// LIKE SO:
$arrLen = count($array);
$array['avgSum'] = $sumTotal/$arrLen;
// IF YOU NEED YOUR DATA IN JSON... THEN RETURN THE JSON ENCODED DATA WITH SUM AS PART OF THE DATA.
// YOU'D HAVE NO NEED FOR array_sum() SINCE YOU DID YOUR PREP-WORK ALREADY...
return json_encode($array);
// ALTERNATIVELY; IF ALL YOU NEED IS JUST THE AVERAGE SUM; YOU COULD AS WELL DIRECTLY RETURN $sumTotal/$arrLen
return ($sumTotal/$arrLen);
}
I found a function on the web, that uses a regular experssion, to iterate over a string and inserts linebreaks after a specified number of characters, so it will fit into a narrow table cell with a fixed width.
here is the function:
/**
* wordwrap for utf8 encoded strings
*
* #param string $str
* #param integer $len
* #param string $what
* #return string
* #author Milian Wolff <mail#milianw.de>
*/
function utf8_wordwrap($str, $width, $break, $cut = false) {
if (!$cut || $_SESSION['wordwrap']) {
$regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.'}#';
} else {
return $str; //if no wordwrap turned on, returns the original string
}
if (function_exists('mb_strlen')) {
$str_len = mb_strlen($str,'UTF-8');
} else {
$str_len = preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $var_empty);
}
$while_what = ceil($str_len / $width);
$i = 1;
$return = '';
while ($i < $while_what) {
preg_match($regexp, $str,$matches);
$string = $matches[0];
$return .= $string.$break;
$str = substr($str, strlen($string));
$i++;
}
return $return.$str;
}
here is the regexp:
#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){20}#
It does its job well, if it's combined with a while loop until there is a line break character in the string.
An example string:
1. first
2. second
3. third
The output of prag_match:
array (
0 => '1. first
2. second
3',
)
so it just counts for the 20th character, and returns it.
What I would need is:
To make it return everything until a new line char (\n) OR if there isn't any, return the first 20 char.
So the output in this case would be something like this:
array (
0 => '1. first',
1 => '2. second',
2 => '3. third'
)
UPDATE:
I tried Steve Robbins's answer and it worked perfectly, until the string had some spec UTF-8 characters in it. It's my fault, I didn't provide a decent example in the first place.
Here is what it does:
<?php
header('Content-type: text/html; charset=UTF-8');
$input = '1. first
2. second
3. third
ez eg nyoulőűúúú3456789öüö987654323456789öü
pam
param';
$output = array();
foreach (explode("\n", $input) as $value) {
foreach (str_split($value, 20) as $v) {
$trimmed = trim($v);
if (!empty($trimmed))
$output[] = $trimmed;
}
}
var_dump($output);
And the output is:
array(8) {
[0]=>
string(8) "1. first"
[1]=>
string(9) "2. second"
[2]=>
string(8) "3. third"
[3]=>
string(20) "ez eg nyoulőűúú�"
[4]=>
string(20) "�3456789öüö987654"
[5]=>
string(13) "323456789öü"
[6]=>
string(3) "pam"
[7]=>
string(5) "papam"
}
http://codepad.org/Gt4CshXt
Why use regex?
<?php
$input = '1. first
2. second
3. third';
$output = array();
foreach (explode("\n", $input) as $value) {
foreach (str_split($value, 20) as $v) {
$trimmed = trim($v);
if (!empty($trimmed))
$output[] = $trimmed;
}
}
var_dump($output);
Gives
array(3) {
[0]=>
string(8) "1. first"
[1]=>
string(9) "2. second"
[2]=>
string(8) "3. third"
}
Example: http://codepad.org/OoillEUu
Thanks everyone for your efforts! I've found the solution here
<?php
header('Content-Type: text/html; charset=utf-8');
$input = '1. first
2. second
3. third
ez eg nyoulőűúúú3456789öüö987654323456789öü
pam
papam';
var_dump(utf8_wordwrap($input,20,"<br>",true));
function utf8_wordwrap($string, $width=20, $break="\n", $cut=false)
{
if($cut) {
// Match anything 1 to $width chars long followed by whitespace or EOS,
// otherwise match anything $width chars long
$search = '/(.{1,'.$width.'})(?:\s|$)|(.{'.$width.'})/uS';
$replace = '$1$2'.$break;
} else {
// Anchor the beginning of the pattern with a lookahead
// to avoid crazy backtracking when words are longer than $width
$pattern = '/(?=\s)(.{1,'.$width.'})(?:\s|$)/uS';
$replace = '$1'.$break;
}
return preg_replace($search, $replace, $string);
}
?>
string '1. first
<br>2. second
<br>3. third
<br>ez eg<br>nyoulőűúúú3456789öüö<br>987654323456789öü
<br>pam
<br>papam<br>' (length=122)