No Output? PHP foreach doesn't seem to work - php

I am trying to form an acronym from a given text. The Idea here is that the first Letter in $text ($text[0]) will be taken and placed inside the array $storage using array_push(). Now, if there is a space inside the array, the letter of the next index should be a part of the Acronym. I am currently not getting an ouput, what am I missing?
public function Acronym($text)
{
$text = str_split($text);
$count = strlen($text);
$storage = array();
for($i=0; $i<$count; $i++)
{
array_push($storage, $text[0]);
if($text[$i]==' ')
{
array_push($storage, $text[$i+1]);
}
foreach($storage as $clean)
{
echo $clean;
}
}
}

Your algorithm suffers from a few fatal flaws:
You're calling strlen() on an array, when you should be calling count():
$text = str_split($text);
$count = count($text);
However, you can index strings as arrays, so you don't need str_split() in this scenario, and you can keep $count = strlen( $text); by removing the call to str_split().
This should only happen once, so it should be outside the loop (This implies starting $i at 1):
array_push($storage, $text[0]);
Your foreach loop that prints the $storage array should be outside of the loop that is creating the acronym.
You can save the overhead of calling a function by using the shorthand array_push() notation. You should use array_push() when adding more than one element to an array. Otherwise, this will suffice:
$storage[] = $text[0];
You need to return something from your function, otherwise you won't be able to access anything outside of it.
Put that all together, and you get this:
public function Acronym($text)
{
$count = strlen( $text);
$storage[] = $text[0];
for( $i = 1; $i < $count; $i++)
{
if( $text[$i] == ' ')
{
$storage[] = $text[$i+1]);
$i++; // Can increment $i here because we know the next character isn't a space
}
}
foreach($storage as $clean)
{
echo $clean;
}
return $storage;
}
That being said, there are far better implementations for forming an acronym giving a string input. Here is one that I can think of:
public function Acronym( $text)
{
$acronym = array();
foreach( explode( ' ', $text) as $word)
{
$word = trim( $word);
$acronym[] = strtoupper( $word[0]);
}
return implode( '', $acronym);
}
Note that both functions will fail for inputs like Hello World. I am leaving it up to the OP to make these modifications (if necessary).

str_split turns the string into an array.
str_length brings the length of a string which you have overwritten with an array already. you need count()

You overwrite your first variable $text
$count = strlen($text);
In this line $text is an array, because you changed it in the first line of your method.
Try inverting the two first lines:
$count = strlen($text);
$text = str_split($text);
Note
This will solve your secondary problem, and enable your algorithm to run without errors. It doesn't fix your algorithm, but at least you will be able to debug it now.

you are running your loop on $count which is getting its value from str_len its an array because of return on $text = str_split($text);
So you have overwritten your $text variable you can fix it by changing order get length first then split.

Related

Replacing ',' characters in only odd positions

I need replace ',' characters with regex in php, but only in odd positions
I have:
{"phone","11975365654","name","John Doe","cpf","42076792864"}
I want replace ',' to ':', but only the odd:
{"phone":"11975365654","name":"John Doe","cpf":"42076792864"}
I'm trying this regex:
preg_replace('/,/', ':', $data)
But it get all quotes and no only the odd.
Can you help me?
Make it simple:
preg_replace('/(("[a-z]+"),(".+?"))+/', '$2:$3', $a)
Rather than regex, this just converts the list to an array (using str_getcsv() to cope with the quotes). Then loops every other item in the list, using that item as the key and the next item as the value. This can then be json_encoded() to give the result...
$data = str_getcsv(trim($input, "{}"));
$output = [];
for ( $i=0, $k=count($data); $i < $k; $i+=2) {
$output[$data[$i]] = $data[$i+1];
}
echo json_encode($output);
It is not ideal to use regex for this task. Having said that, if you know that your input can be matched by a simple regex, this should do it :
$str = '{"phone","11975365654","name","John Doe","cpf","42076792864"}';
$result = preg_replace('/,(.*?(?:,|[^,]*$))/ms', ':\\1', $str);
This lenient to some extra characters but it will fail if any string contains commas
Example
Here's an example of using standard PHP functions:
$input = '{"phone","11975365654","name","John Doe","cpf","42076792864"}';
$dataIn = str_getcsv(trim($input, '{}'));
$keys = array_filter($dataIn, function ($key) { return !($key & 1); }, ARRAY_FILTER_USE_KEY);
$values = array_filter($dataIn, function ($key) { return $key & 1; }, ARRAY_FILTER_USE_KEY);
$DataOut = array_combine($keys, $values);
$output = json_encode($DataOut);
echo $output;
This code is a lot longer than using a regex, but it is probably easier to read and maintain in the long run. It can cope with commas in the values.
Another option could be using array_splice and loop while there are still elements in the array:
$str = '{"phone","11975365654","name","John Doe","cpf","42076792864"}';
$data = str_getcsv(trim($str, '{}'));
$result = array();
while(count($data)) {
list($k, $v) = array_splice($data, 0, 2);
$result[$k] = $v;
}
echo json_encode($result);
Output
{"phone":"11975365654","name":"John Doe","cpf":"42076792864"}

Compare string from input field with value in multidimension array

$klasseinput = strtoupper(trim($_POST["klasseliste"]));
$data = file('student.txt');
$data = array_filter($data);
foreach($data AS $row){
$student[] = explode(';', $row);
}
$antall = count($student);
for ($i = 0; $i < $antall; $i++){
if($klasseinput == $student[$i][3]){
print('<tr><td>'.$student[$i][0]."</td><td>".$student[$i][1]."</td><td>".$student[$i][2]."</td><td>".$student[$i][3]."</td></tr>");
}
}
/////////STUDENT.txt//////////
ph;petter;hanssen;IT1
gb;Geir;Bjarvin;IT2
mj;Marius;Johansen;IT3
/////////////////////////////
I am trying to compare an input form with an item in the multidimension array, but even tho the variable from the input field is exactly the same as the value in the array, it doesnt pass the if check.
$student[0][3] = IT1
$student[1][3] = IT2
$student[2][3] = IT3
If you have made sure there is no white space spoiling the comparison, then you might find a function like this useful to look at the strings on both sides of the comparison. You might find there are spurious characters causing trouble.
function hexdump($str)
{
for($i=0; $i<strlen($str);$i++)
{
echo "[$i] [".bin2hex($str[$i])."] [".$str[$i]."]<br />";
}
}
For instance, the string read from the file might contain CR LF characters. You could get rid of them using str_replace().
Thanks to Ravinder Reddy for the answer that was simple and worked for me:
" trim the value for \t\n if($klasseinput == trim($student[$i][3])){ "

Cut string in PHP at nth-from-end occurrence of character

I have a string which can be written in a number of different ways, it will always follow the same pattern but the length of it can differ.
this/is/the/path/to/my/fileA.php
this/could/also/be/the/path/to/my/fileB.php
another/example/of/a/long/address/which/is/a/path/to/my/fileC.php
What I am trying to do is cut the string so that I am left with
path/to/my/file.php
I have some code which I got from this page and modified it to the following
$max = strlen($full_path);
$n = 0;
for($j=0;$j<$max;$j++){
if($full_path[$j]=='/'){
$n++;
if($n>=3){
break 1;
}
}
}
$path = substr($full_path,$j+1,$max);
Which basically cuts it at the 3rd instance of the '/' character, and gives me what is left. This was fine when I was working in one environment, but when I migrated it to a different server, the path would be longer, and so the cut would give me too long an address. I thought that rather than changing the hard coded integer value for each instance, it would work better if I had it cut the string at the 4th from last instance, as I always want to keep the last 4 'slashes' of information
Many thanks
EDIT - final code solution
$exploded_name = explode('/', $full_path);
$exploded_trimmed = array_slice($exploded_name, -4);
$imploded_name = implode('/', $exploded_trimmed);
just use explode with your string and if pattern is always the same then get last element of the array and your work is done
$pizza = "piece1/piece2/piece3/piece4/piece5/piece6";
$pieces = explode("/", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2
Then reverse your array get first four elements of array and combine them using "implode"
to get desired string
This function below can work like a substr start from nth occurrence
function substr_after_nth($str, $needle, $key)
{
$array = explode($needle, $str);
$temp = array();
for ($i = $key; $i < count($array); $i++) {
$temp[] = $array[$i];
}
return implode($needle, $temp);
}
Example
$str = "hello-world-how-are-you-doing";
substr after 4th occurrence of "-" to get "you-doing"
call the function above as
echo substr_after_nth($str, "-", 4);
it will result as
you-doing

php reading in strings from text area

$data = explode("\n", trim($_GET['names']));
while($i < count($data)) {
if(!in_array($data[$i], $unique_names)){
$unique_names[] = $names[$i];
}
$i = $i + 1;
}
I am trying to accept only unique results from a textarea using this php code. It is not working because every string has an extra blank space, except for the last one.
I.E.
"jeff "
"fred "
"bill "
"jeff"
so jeff will be added twice.
My question is:
How Do I get rid of that space?? I tried trim and it won't perform as intended.
First of all, you don't need to find unique values manually, you can use array_unique(). Secondly, trim() doesn't work on arrays.
Try:
$raw_names = explode("\n", $_GET['names']);
$trimmed_names = array_map('trim', $raw_names);
$unique_names = array_unique($trimmed_names);
Use trim(string) to remove whitespace from the start and end. http://php.net/manual/en/function.trim.php
Inspired by kba :
$data = explode("\n", trim($_GET['names']));
foreach ($data as &$e) {
$e = trim($e);
}
$unique_names = array_unique($data);

Split an array with a regular expression

I'm wondering if it is possible to truncate an array by using a regular expression.
In particular I have an array like this one:
$array = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc","AaDa"...);
I have this string:
$str = "AC";
I'd like the slice of $array from the start to the last occurrence of a string matching /A.C./ (in the sample, "AaCc" at index 5):
$result = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc");
How can I do this? I thought I might use array_slice, but I don't know how to use a RegEx with it.
Here's my bid
function split_by_contents($ary, $pattern){
if (!is_array($ary)) return FALSE; // brief error checking
// keep track of the last position we had a match, and the current
// position we're searching
$last = -1; $c = 0;
// iterate over the array
foreach ($ary as $k => $v){
// check for a pattern match
if (preg_match($pattern, $v)){
// we found a match, record it
$last = $c;
}
// increment place holder
$c++;
}
// if we found a match, return up until the last match
// if we didn't find one, return what was passed in
return $last != -1 ? array_slice($ary, 0, $last + 1) : $ary;
}
Update
My original answer has a $limit argument that served no purpose. I did originally have a different direction I was going to go with the solution, but decided to keep it simple. However, below is the version that implements that $limit. So...
function split_by_contents($ary, $pattern, $limit = 0){
// really simple error checking
if (!is_array($ary)) return FALSE;
// track the location of the last match, the index of the
// element we're on, and how many matches we have found
$last = -1; $c = 0; $matches = 0;
// iterate over all items (use foreach to keep key integrity)
foreach ($ary as $k => $v){
// text for a pattern match
if (preg_match($pattern, $v)){
// record the last position of a match
$last = $c;
// if there is a specified limit, capture up until
// $limit number of matches, then exit the loop
// and return what we have
if ($limit > 0 && ++$matches == $limit){
break;
}
}
// increment position counter
$c++;
}
I think the easiest way might be with a foreach loop, then using a regex against each value - happy to be proven wrong though!
One alternative could be to implode the array first...
$array = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc","AaDa"...);
$string = implode('~~',$array);
//Some regex to split the string up as you want, guessing something like
// '!~~A.C.~~!' will match just what you want?
$result = explode('~~',$string);
If you'd like a hand with the regex I can do, just not 100% on exactly what you're asking - the "A*C*"-->"AaCc" bit I'm not too sure on?
Assuming incremental numeric indices starting from 0
$array = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc","AaDa");
$str = "AC";
$regexpSearch = '/^'.implode('.',str_split($str)).'.$/';
$slicedArray = array_slice($array,
0,
array_pop(array_keys(array_filter($array,
function($entry) use ($regexpSearch) {
return preg_match($regexpSearch,$entry);
}
)
)
)+1
);
var_dump($slicedArray);
PHP >= 5.3.0 and will give a
Strict standards: Only variables should be passed by reference
And if no match is found, will still return the first element.

Categories