Cannot conditionally push element into subarray -- instead it overwrites first character - php

I have this code which works as I expect:
$somearr['some']='value';
$arr[]="first";
$arr['first'][]=$somearr['some'];
echo "<br> Var dump of arr: " . var_dump($arr);
Yields:
array (size=2)
0 => string 'first' (length=5)
'first' =>
array (size=1)
0 => string 'value' (length=5)
Perfect.
Now attempting to apply the same principle (I assume) in my project:
function get_field_names($database, $table) {
$show_statement = "DESCRIBE `" . $database . "`.`" . $table . "`";
$column_result = mysql_query($show_statement);
if (mysql_num_rows($column_result) > 0) {
$f = 0;
while ($row = mysql_fetch_assoc($column_result, MYSQL_ASSOC)) {
$field_names[$f] = $row['Field'];
if ($row['Key'] != "") {
$field_names[$f][0] = $row['Key'];
}
$f++;
}
}
return $field_names;
}
But instead of creating a second dimension to my array $field_names[$f][0] with the value of $row['Key'], instead the first character in the string of $field_names[$f] is overwritten with the first character in $row['Key'] such that $field_names[$f] contains the string: "field_name" and after $field_names[$f][0] = $row['Key'] where $row['Key'] == "PRI", I get : "Pield_name".
I am sure I am misunderstanding the array $row, but I am beginning to go in circles.

That's easily explained by revisiting your original example:
$arr[]="first";
$arr['first'][]=$somearr['some'];
This doesn't do what you think it does. The first line doesn't create a new array key first. It just assigns a value to the indexed entry [0].
The second line however assigns a value to the alphanumeric key [first]. That's two distinct sub-entries in the $arr array.
In your second example, you are overwriting values:
$field_names[$f] = 'string...';
$field_names[$f][0] = 'something else...';
You can only have one array entry at the [$f] key. You cannot have a shared spot with a string and an array.
What actually happens here is that the second line is assigning a value to the first array-like index of the 'string...'. It's equivalent to the alternative string-index syntax:
$field_names[$f]{0} = 'something else...';
^
|
Not an array index. Because a string was here first.
Anyway, you cannot share an entry as string and key. That's the whole story. - I think it's cursorily explained somewhere in the manual under arrays.

This is because you can treat any string in PHP like an array
$test = "Hello, World";
echo $test[0];
Will result in "H" being echo'ed. What you are telling you code in
$field_names[$f][0] = $row['Key'];
is replace the first character in the string $field_names[$f] with $row['Key']. However since it is only 1 character that we are replacing PHP just uses the first character in $row['Key'] thus you get "Pield_name", the "P" from PRI replaced in for the "F" which was at the first position in the "string array"
I'm still confused however to what you want to do. If you could map out what you want the array to look like after you insert(?) the $row['Key']. I can help you with the code
EDIT:
The reason you top code is working is you are simply not specifying a key for your first item you add to the array:
$arr[]="first"; //Inserts string "first" at pos 0 of array same as $arr[0]="first";
$arr['first'][]=$somearr['some']; //Inserts array into $arr using key 'first'
echo "<br> Var dump of arr: " . var_dump($arr);
The same could be achieved with this code
$arr =array(
0 => 'first',
'first' => $somearr['some']
)

Related

How to create and fill a new associative array with values created in a for each?

I am a noob attempting to solve a program for a word search app I am doing. My goal is to take a string and compare how many times each letter of that string appears in another string. Then put that information into an array of key value pairs, where the key is each letter of the first string and the value is the number of times. Then order it with ar(sort) and finally echo out the value of the letter that appears the most (so the key with the highest value).
So it would be something like array('t' => 4, 'k' => '9', 'n' => 55), echo the value of 'n'. Thank you.
This is what I have so far that is incomplete.
<?php
$i = array();
$testString= "endlessstringofletters";
$testStringArray = str_split($testString);
$longerTestString= "alphabetalphabbebeetalp
habetalphabetbealphhabeabetalphabetalphabetalphbebe
abetalphabetalphabetbetabetalphabebetalphabetalphab
etalphtalptalphabetalphabetalbephabetalphabetbetetalphabet";
foreach ($testStringArray AS $test) {
$value = substr_count($longerTestString, $testStringArray );
/* Instead of the results of this echo, I want each $value to be matched with each member of the $testStringArray and stored in an array. */
echo $test. $value;
}
/* I tried something like this outside of the foreach and it didn't work as intended */
$i = array_combine($testStringArray , $value);
print_r($i);
If I understand correctly what you are after, then it's as simple as this:
<?php
$shorterString= "abc";
$longerString= "abccbaabaaacccb";
// Split the short sring into an array of its charachters
$stringCharachters = str_split($shorterString);
// Array to hold the results
$resultsArray = array();
// Loop through every charachter and get their number of occurences
foreach ($stringCharachters as $charachter) {
$resultsArray[$charachter] = substr_count($longerString,$charachter);
}
print_r($resultsArray);

Unserialsed Array giving the weirdest results

I've a really odd issue today. I've got a serialised array that looks like this:
a:4:{i:0;s:7:"Perfect";i:1;s:10:"jawel hoor";i:2;s:14:"Ach jawohl joh";i:3;s:2:"Ja";}
Then after I execute this code:
include '../../database/connect.php';
Class Calc {
function getPrice($id) {
$Db = new Db();
$sth = $Db->dbh->prepare("SELECT * FROM orders WHERE id = :id");
$sth->execute(array(':id'=>$id));
$are_you_serial = $sth->fetchAll();
foreach($are_you_serial as $row) {
$serialised = $row['reply_array'];
$product_id = $row['product_id'];
$user_id = $row['user_id'];
}
$array = unserialize($serialised);
foreach($array as $row) {
echo $row[1];
}
}
}
$calc = new Calc();
$calc->getPrice(11);
eaca comes out. When I call row 0 PjAJ comes out.
When I call row 2 this seems to be the error:
rwh
Notice: Uninitialized string offset: 2 in index.php on line 29
This is what the array looks like if I just print_r the $array:
Array
(
[0] => Perfect
[1] => jawel hoor
[2] => Ach jawohl joh
[3] => Ja
)
I can also call $array[0] and it'll show the right things but once I put it in the foreach it doesn't work anymore.
Your first foreach keeps reassigning the variables, so $serialised (should be $serialized BTW) will only ever hold the value of the last row by the time you're actually calling unserialize. I'll add what I think you want bellow, but for now, some more details on why you're getting the "weird" or unexpected output:
A little info on how to read the PHP serialized format:
a:4:{i:0;s:7:"Perfect";i:1;s:10:"jawel hoor";...
a:4:{: What follows is an array, containing 4 key-value pairs
i:0;: An integer, value 0. Because this is part of an array, all odd values are keys, even values are values, so the first index of the array is 0
s:7:"Perfect";: A string, 7 chars long, and the string itself is "Perfect" (without the quotes)
Same applies to objects that are serialized:
O:8:"stdClass":2:{s:3:"bar";i:123;s:3:"foo";i:456;}
o:8:"stdClass":2:{: An object, the class name of which is 8 chars long (stdClass), with 2 properties set
s:3:"bar";i:123;: The property name is a 3-char long string ("bar"), its value is an int (123)
s:3:"foo";i:456;: 3-char long property ("foo") with value 456
}: End of serialized object
Knowing this, you should be able to work out that what you're doing with the data after you've unserialized, ie this:
foreach ($array as $row) {
echo $row[1];
}
Is just all shades of wrong, the value of $row will be a string, and getting an index/offset of a string is possible (preferably using the {} notation, as in $row{1}), but it'll return the character at offset n, where n is the digit/key between brackets. Strings are, like arrays, zero-indexed BTW, so $string = 'foo'; echo $string{0}; will echo "f", and echo $string{1}; will echo "o".
What you want, then is to write:
foreach ($array as $row) {
echo $row;
}
or shorter:
echo implode(PHP_EOL, $array);//PHP_EOL to add linebreaks between the strings
Like I said at the beginning, you're only really processing the very last serialized value, what you actually want is probably something more like this:
$unserialized = [];
foreach ($sth->fetchAll() as $row) {
//add unserialized values to an array
$unserialized[] = unserialize($row['reply_array']);
}
//$unserialized is now an array of arrays
foreach ($unserialized as $rowNr => $array) {
echo 'Row #', $rowNr+1, ': ', PHP_EOL,
implode(PHP_EOL, $array);
}
That ought to get you started...

Grouping in PHP using a character

I have an array like:
array{
0 => string 'B.E - ECE',
1 => string 'B.E - EEE',
2 => string 'Msc - Maths',
3 => string 'Msc - Social',
}
So how can I make the array into groups like:
B.E. => ECE, EEE
Msc => Maths,Social
?
I want to do it in PHP. Can anybody help me how to achieve it ?
So is your array split by the "-" character?
so it's Key - Value pairs split by commas?
Ok -
(edit: section removed to clarify answer)
Following conversation and some rearrangement of the question, a second try at a solution, with the above assumptions, try this:
$array = array {
0 => string 'B.E - ECE' (length=9)
1 => string 'B.E - EEE' (length=9)
2 => string 'Msc - Maths' (length=11)
3 => string 'Msc - Social' (length=12)
}
foreach ($array as $row){
$piece = explode("-",$row);
$key = $piece[0];
$newArray[$key][] = $piece[1];
unset($piece);
}
unset($row) ///tidy up
This will output two arrays each of two arrays:
$newArray[Msc] = array("Maths","Social");
$newArray[B.E] = array("ECE","EEE");
What I did was cause the Foreach loop to automatically add onto the array if the key exists with $newArray[$key][] so that the values are automatically collected by key, and the key is defined as the first half of the original array values.
Printing:
To print the result:
foreach($newArray as $key=>$newRow){
/// there are two rows in this case, [B.E] and [MSc]
print $key.":<br>";
print "<pre>";
///<pre> HTML tag makes output use linebreaks and spaces. neater.
print_r($newRow);
///alternatively use var_dump($newRow);
print "</pre>";
}
Alternatively if you wish to print a known named variable you can write:
print_r($newArray['B.E']);
Which will print all the data in that array. print_r is very useful.
what you want is php's explode. Not sure if this will give you the perfect answer but should give you an idea of what to do next.
$groupedArray = array();
foreach($array as $row){
$split = explode(" - ",$row);
$groupedArray[] = $split[0];
}
array_unique($groupedArray); //This will give you the two groupings
foreach($array as $row){
$split = explode(" - ",$row);
$pos = array_search($split[0],$groupedArray);
if($pos !== FALSE){
$groupedArray[$pos][] = $split[1];
}
}
This should give you a full formatted array called $groupedArray where $array is the array you already have.
Hope this helps!

Indexing into an array returned by a variable variable in PHP

I'm just wondering about how variable variables that point to Arrays handle. Take the code below:
$a = new stdClass();
$a->b = array('start' => 2);
$c = 'b';
$d = 'start';
print $a->$c; // => Array
print $a->$c['start']; // => Array
print $a->$c[0]; // => Array
print $a->$c[0][0]; //=> PHP Fatal error: Cannot use string offset as an array in php shell code on line 1
The first print I expect, the second one I don't, or the 3rd. The 4th is expected after realizing that the evaluation of $a->$c is apparently a string. But then why does this work:
$t = $a->$c;
print $t['start']; //=> 2
I'm asking more because I'm curious than I need to know how to nicely do
$e = 'start';
$a->$c[$e]
Anyone know why I can't index directly into the array returned by the variable variable usage?
It comes down to order of operations and how PHP type juggles. Hint: var_dump is your friend, echo always casts to a string so it is the worst operation for analyzing variable values, esp in debug settings.
Consider the following:
var_dump($a->$c); // array (size=1) / 'start' => int 2
var_dump($a->$c['start']); // array (size=1) / 'start' => int 2
var_dump($a->b['start']); // int 2
var_dump($c['start']); // string 'b' (length=1)
The key here is how PHP interprets the part of $c['start'] (include $c[0] here as well). $c is the string 'b', and when attempting to get the 'start' index of string 'b' this simply returns the first character in the string, which happens to simply be the only letter (b) in the string. You can test this out by using $c = 'bcdefg'; - it'll yield the same result (in this specific case). Also, $c['bogus'] will yield the exact same thing as $c['start']; food for thought, and make sure you do the required reading I linked to.
So with this in mind (knowing that $c['start'] reluctantly returns 'b'), the expression $a->$c['start'] is interpreted at $a->b. That is, the order is $a->($c['start']) and not ($a->$c)['start'].
Unfortunately you can't use () nor {} to steer the parser (PHP SCREAMs), so you won't be able to accomplish what you want in a single line. The following will work:
$e = 'start';
$interim = $a->$c;
echo $interim[$e];
Alternatively, you can cast your arrays as objects (if you have the luxury):
$a->$c = (object) $a->$c; // mutate
var_dump($a->$c->$e);
$interim = (object) $a->$c; // clone
var_dump($interim->$e);
...by the way, referring back up to $c['start'] and $c[0], in regards to $c[0][0] you simply can't do this because $c[0] is the character b in string 'b'; when access the character/byte b it will not have a property of [0].
$a->$c[0]; is actually equal to: array('start' => 0)
so when you did:
print $a->$c[0][0];
You are trying to load an array element from $a->$c[0] at index 0 which does not exists.
however, this will work:
print $a->$c[0]['start'];

each() and list() function

I don't understand the each() and the list() function that well. Can anyone please give me a little more detail and explain to me how can it be useful?
Edit:
<?php
$foo = array("bob", "fred", "jussi", "jouni", "egon", "marliese");
$bar = each($foo);
print_r($bar);
?>
Array
(
[1] => bob
[value] => bob
[0] => 0
[key] => 0
)
So does this mean in array[1] there's the value bob, but it's clearly in array[0]?
list is not a function per se, as it is used quite differently.
Say you have an array
$arr = array('Hello', 'World');
With list, you can quickly assign those different array members to variables
list($item1, $item2) = $arr; //$item1 equals 'Hello' and $item2 equals 'World'
The each() function returns the current element key and value, and moves the internal pointer forward.
each()
The list function — Assigns variables as if they were an array
list()
Example usage is for iteration through arrays
while(list($key,$val) = each($array))
{
echo "The Key is:$key \n";
echo "The Value is:$val \n";
}
A very common example for list is when thinking about CSV files. Imagine you have a simple database stored as CSV with the columns id, title and text, such a file could look like this:
1|Foo|Lorem ipsum dolor|
2|Bar|sit amet|
...
Now when you parse this file you could do it like this, using the list function:
$lines = file( 'myFile.csv' );
for ( $i = 0; $i < count( $lines ); $i++ )
{
list( $id, $title, $text, $null ) = explode( '|', $lines[$i], 4 );
echo "Id: $id, Title: $title\n$text\n\n";
}
The other function, each, is basically just an old way to walk through arrays, using internal pointers. A more common way to do that is by using foreach now.
Edit: its probably worth noting that each has been deprecated
Warning: This function has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged
lets look first at each() : it returns the current value (at first that's $array[0 | "first value in association array ] . so
$prices = ('x'=>100 , 'y'=>200 , 'z'= 300 );
say I wanna loop over these array without using a foreach loop .
while( $e = each($prices) ){
echo $e[key] . " " . $e[value] . "<br/>" ;
}
when each reaches point at a non existing element that would cause
the while loop to terminate .
When you call each(), it gives you an array with four values and the four indices to the array locations.The locations 'key' and 0 contain the key of the current element, and the locations 'value' and 1 contain the
value of the current element.
so this loop would list each key of the array a space and the value then
secondly lets look at list() .
it basically will do the same thing with renaming of 'value' and 'key' although it has to be use in conjunction with each()
while( list($k , $v ) = each($prices) ){
echo $k /*$e[key]*/ . " " . $v /*$e[value]*/ . "<br/>" ;
}
So in a nutshell each() iterates over the array each time returning an array . list() rename the value , key pairs of the array to be used inside the loop .
NOTICE : reset($prices) :
resets each() pointer for that array to be the first element .
http://www.php.net/list
list isn't a function, it is a language construct. It is used to assign multiple values to different variables.
list($a, $b, $c) = array(1, 2, 3);
Now $a is equal to 1, and so on.
http://www.php.net/each
Every array has an internal pointer that points to an element in its array. By default, it points to the beginning.
each returns the current key and value from the specified array, and then advances the pointer to the next value. So, put them together:
list($key, $val) = each($array);
The RHS is returning an array, which is assigned to $key and $val. The internal pointer in `$array' is moved to the next element.
Often you'll see that in a loop:
while(list($key, $val) = each($array)):
It's basically the same thing as:
foreach($array as $key => $val):
To answer the question in your first edit:
Basically, PHP is creating a hybrid array with the key/value pair from the current element in the source array.
So, you can get the key by using $bar[0] and the value by using $bar[1]. OR, you can get the key by using $bar['key'] and the value using $bar['value']. It's always a single key/value pair from the source array, it's just giving you two different avenues of accessing the actual key and actual value.
Say you have a multi-dimensional array:
+---+------+-------+
|ID | Name | Job |
| 1 | Al | Cop |
| 2 | Bob | Cook |
+---+------+-------+
You might do something like:
<?php
while(list($id,$name,$job) = each($array)) {
echo "".$name." is a ".$job;
}
?>
Using them together is, basically, an early way to iterate over associative arrays, especially if you didn't know the names of the array's keys.
Nowadays there's really no reason I know of not to just use foreach instead.
list() can be used separately from each() in order to assign an array's elements to more easily-readable variables.

Categories