json in perl deserialization length count doesn't work - php

How do iterate through a deserialized json string? I can't get the right number of values right now it doesn't count right.
my $list = request("http://localhost/getjson.php");
my $deserialize = from_json( $list );
print Dumper($deserialize);
$VAR1 = [
'ab',
'cc',
'de',
'aer',
'ffe',
'cer',
'dad',
'efef',
'afaf',
'ege',
'grsc',
'cegg',
'cegg',
'cegg/aaa.html',
'eggt',
'ttt'
];
print length($deserialize);
13 ?? it should say 16

You are getting back an array reference not an array. You need to dereference the value.
my #array = #$deserialize; # or #{ $deserialize }
print scalar #array;
Moreover, if you want to iterate over the array you can just use for
for (#$deserialize) {
# do stuff

You are actually working with reference to the results. Since JSON can contain all sorts of different results, decode_json won't return a list specifically.
So you need to dereference the variable that you have: $deserialize
Additionally, you don't really want to be using the length function. If you print the integer value (or scalar value) of an array, it will return it's size.
So here's what you want:
my $list = request("http://localhost/getjson.php");
my $deserialize = from_json( $list );
print scalar (#{$deserialize});
That will print the size of the array.
If you want to just start by working with an array you can do:
my $list = request("http://localhost/getjson.php");
my $deserialize = from_json( $list );
my #json_array = #{$deserialize});
print scalar (#json_array);

From perldoc -f length:
This function cannot be used on an entire array or hash to find
out how many elements these have. For that, use "scalar
#array" and "scalar keys %hash", respectively.
You cannot use length to find out the size of an array. To do that, use the advice above.
Your bug gives you a false value because you are taking the length of the array reference, which in string context will be something like ARRAY(0x22d0a88), which in your case seemed to be 13 characters long. E.g. the equivalent of:
print length "ARRAY(0x22d0a88)";
As a curious side note, if you would do length(#array), it will actually return the length of the length of the array. E.g. an array of size 16 would return 2, because the string "16" is two characters long.

Related

Undesired reordering of keys in PHP array

I have a quick question. When building an associative array key casting rules mean that strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8. (On the other hand "08" will not be cast, as it isn't a valid decimal integer.) See for example: http://php.net/manual/en/language.types.array.php
The problem I have is that my keys are mixed integer and string .. meaning that when the associative array is built, all keys are reordered with numerical keys appear first before string. This is a sample of what I get in my console log:
...
2032: "9371.84"
2033: "9351.60"
2034: "9331.36"
2035: "9311.12"
ID: "1"
Misc1: "Russian Federation - Conventional"
Misc2: "RUS.Con1"
Misc3: "4"
Misc4: ""
... etc.
How can I avoid this issue, so that the associative array does not re-order my keys?
As an FYI, this is how I generate my array in PHP:
while ($array = mysqli_fetch_assoc($result)) {
$experiment[] = $array;
};
Thank you for your time,
G.
Adding an index to an array in PHP like this:
$array[] = ['another array'];
Will increment the indexes.
You can however specify a string for the key, or cast the integers to strings.
The workaround for the issue I have found is to avoid the associative array structure. This is what my loop looks like now:
while ($array = mysqli_fetch_assoc($result)) {
$experiment[0] = array_keys($array);
$experiment[] = array_values($array);
};
The annoying thing is that $experiment[0] = array_keys($array); gets looped uneccessarily... but at least I get the result that I am looking for and the keys are not cast and re-ordered by the associative array.
If anybody knows how to avoid the unecessary looping for $experiment[0], then please let me know :-)

How does PHP determine whether a variable is an array or a string?

I'm confused as to how PHP determines whether a variable is a string or an array. It seems to depend on the operators being used.
Here's an example:
<?php
$z1 = "abc";
$out = "";
for ($i = 0; $i < strlen($z1); $i++)
{
// $out[$i] = $z1[$i];
$out = $out.$z1[$i];
}
print $out;
?>
In the above version $out becomes a string (print $z1 shows "abc"). However, if I use the first line $out[$i] = $z1[$i];, $out becomes an array.
Can someone please clarify why this happens, and if its possible to access a string's characters with square brackets without converting the output to an array?
The definition of a string in PHP is considered a set of data writen in linear format (i.e: $var = "username=SmokeyBear05,B-day=01/01/1980";)
An array however is a set of data broken down into several parts. A sort of list format if you will. As an example I've written the data string from before, into an array format...
Array(['username']=>"SmokeyBear05", ['B-day']=>"01/01/1980")
Now strings are generally defined as such: $var="Your String";
Arrays however can be written in three different formats:
$var1 = array('data1','data2','data3');
$var2 = array('part A'=>'data1','part B'=>'data2','part C'=>'data3');
The output of var1 starts the index value at 0. The output of var2 however, sets a custom index value. Now the third way to write an array (least common format) is as such:
$var[0]="data1";
$var[1]="data2";
$var[2]="data3";
This takes more work, but allows you to set the index.
Most web developers working with PHP will set data from an external source as a string to deliver it to another PHP script, and then break it down into an array using the explode() function.
When you define variable $out = "", for loop doesn't understand this variable as string value. If you set $out[$i] value, by default, it was treated as an array.
If you want to get the output result as string value, you can define $out = "a" to make sure it's a string variable.

Can Indexed Arrays be used as associative arrays?

I know that in PHP an indexed array that looks like:
$array = ("hello", "world")
is the same as an associative array that looks like:
$array = (0 => "hello", 1 => "world");
so my question is if code like this is valid :
$hello = $array[$array["hello"]];
my thinking is that it translates to
$hello = $array[0]
, which will equal
$hello = "hello"
. In other words, will
$array["hello"]
equal 0?
No, you cannot fetch a key of some array element by its value right away... unless you switch keys and values with array_flip:
$arr = array('hello', 'world');
$arr = array_flip($arr);
print $arr['hello']; // 0
Let's walk through the thinking:
$array = ("hello", "world") // This is implicitly indexed by integer.
is the same as:
$array = (0 => "hello", 1 => "world"); // Explicit indexing.
You can verify by doing print_r($array); In either case, the output would show an indexed array. PHP arrays are all associative. Even if you did not specify a key, the values in an array are ordered by integer index numbers.
Now let's take a look at:
so my question is if code like this is valid :
$hello = $array[$array["hello"]];
This is where the code will break. Why?
$array["hello"] is not a valid value. What this is referencing is "the value of the array's list at index "hello".
However, array("hello", "world") does not have an index key of "hello". Rather, it has a value "hello" which has implicitly the key index 0.
Make sure to read up on PHP arrays and understand that:
PHP arrays are all associative; keys can be strings, or if not explicitly set, will be integers.
Associative arrays are in the form of key => value pairs. If you have a key, you can find the value associated with it.
When trying to get a value from a PHP array, the syntax is: $array['key'] or in the case of multidimensionals $array['firstlevelkey']['secondlevelkey'] etc. The value that gets returned would be the value of the key => value pair at that particular key.
I hope this is helpful!
No, since "hello" is not a valid key in $array.
You can check if a key exist using array_key_exists(key,*array*)

Deleting all array values from a specific offset and on

I have an array that has 120~ or so offsets and I was wondering how you would delete all the values of said array after a certain offset containing a specified string. For example: Offset [68] has the string 'Overflow'. I want to remove everything including 68 and beyond and rebuild the array (with its current sorting in tact).
I tried messing around with slice and splice but I can't seem to get it to return the right values. I was also thinking of just grabbing the offset number that contains 'Overflow' and then looping it through a for statement until $i = count($array); but that seems a little more intensive than it should be.
Would this be the best way? Or is there some function to do this that I'm just using wrong?
Use array_slice().
$desired = array_slice($input, 0, $upTo);
First you need to find the string occurrence in the array, and, if the value was found, trim the array from that point;
function removeString($string, $array)
{
# search for '$string' in the array
$found = array_search($string, $array);
if ($found === false) return $array; # found nothing
# return sliced array
return array_slice($array, $found);
}
And if you need to make the array sequential (to avoid surprises due to missing offsets), you can always add in the first line $array = array_values($array). This will reorganize the array values in a new array with ordered offsets: 0, 1, 2, 3, 4...

Which is proper form?

PHP.
$a['0']=1;
$a[0]=2;
Which is proper form?
In the first example you use a string to index the array which will be a hashtable "under the hood" which is slower. To access the value a "number" is computed from the string to locate the value you stored. This calculation takes time.
The second example is an array based on numbers which is faster. Arrays that use numbers will index the array according to that number. 0 is index 0; 1 is index 1. That is a very efficient way of accessing an array. No complex calculations are needed. The index is just an offset from the start of the array to access the value.
If you only use numbers, then you should use numbers, not strings. It's not a question of form, it's a question of how PHP will optimize your code. Numbers are faster.
However the speed differences are negligible when dealing with small sizes (arrays storing less than <10,000 elements; Thanks Paolo ;)
In the first you would have an array item:
Key: 0
Index: 0
In the second example, you have only an index set.
Index: 0
$arr = array();
$arr['Hello'] = 'World';
$arr['YoYo'] = 'Whazzap';
$arr[2] = 'No key'; // Index 2
The "funny" thing is, you will get exactly the same result.
PHP (for whatever reason) tests whether a string used as array index contains only digits. If it does the string is converted to int or double.
<?php
$x=array(); $x['0'] = 'foo';
var_dump($x);
$x=array(); $x[0] = 'foo';
var_dump($x);
For both arrays you get [0] => foo, not ["0"] => foo.
Or another test:<?php
$x = array();
$x[0] = 'a';
$x['1'] = 'b';
$x['01'] = 'c';
$x['foo'] = 'd';
foreach( $x as $k=>$v ) {
echo $k, ' ', gettype($k), "\n";
}0 integer
1 integer
01 string
foo string
If you still don't believe it take a look at #define HANDLE_NUMERIC(key, length, func) in zend_hash.h and when and where it is used.
You think that's weird? Pick a number and get in line...
If you plan to increment your keys use the second option. The first one is an associative array which contains the string "0" as the key.
They are both "proper" but have the different side effects as noted by others.
One other thing I'd point out, if you are just pushing items on to an array, you might prefer this syntax:
$a = array();
$a[] = 1;
$a[] = 2;
// now $a[0] is 1 and $a[1] is 2.
they are both good, they will both work.
the difference is that on the first, you set the value 1 to a key called '0'
on the second example, you set the value 2 on the first element in the array.
do not mix them up accidentally ;)

Categories