PHP array with both a numbered index and named index? - php

I would think this would be easier to find but I've been scouring google with no luck. Can you create an array with both a numbered and named index? I know it has to be possible because mysqli_fetch_array returns one, but I can't find any reference to it.
Thanks.

As per official documentation:
An array in PHP is actually an ordered map. A map is a type that associates values to keys.
The key can either be an integer or a string. The value can be of any type.

Nothing to it:
$x = array();
$x['foo'] = 'bar';
$x[1] = 'baz';
Use any key you want. As long as whatever you're using for a key is an int or a valid string, it can be a key.

Yes. PHP arrays can have mixed keys (strings and integers). A reference to it can be found in the docs here: http://php.net/manual/en/language.types.array.php.
An array in PHP is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more. As array values can be other arrays, trees and multidimensional arrays are also possible.
Check Example #3:
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
outputs:
array(4) {
["foo"] => string(3) "bar"
["bar"] => string(3) "foo"
[100] => int(-100)
[-100] => int(100)
}

Related

php, array_merge_recursive works well with string keys only

$array1 = [
'1' => '11',
'b' => 1,
3 => 33,
8 => 8
];
$array2 = [
'1' => '22',
'b' => 2,
3 => 44,
9 => 9
];
$merged = array_merge_recursive($array1, $array2);
and the result is:
array(7) {
[0]=>
string(2) "11"
["b"]=>
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
[1]=>
int(33)
[2]=>
int(8)
[3]=>
string(2) "22"
[4]=>
int(44)
[5]=>
int(9)
}
so lets take a glance: the only part is the 'b' keys, they are actually works. I dont want to overwrite anything of it but putting them together to an array. Thats good! But then keys the other numeric keys (int or string) are screwed up.
I want to have this as result:
[
'1' => ['11', '22']
'b' => [1, 2]
[3] => [33, 44]
[8] => 8,
[9] => 9
]
possible?
EDIT: of course keys "1" and 1 - string vs int key are the same
Let's break down this question into to separate problems:
When a key in the second array exist in the first array, you want to create an array and make the value the first element of that array.
To be honest, I don't know an easy way of solving this. I'm not sure there is one. And even if, I'm not sure you really want it. Such a function will lead to arrays having values that are a string or an array. How would you handle such an array?
Update: Well, there is one. Your example already shows that array_merge_recursive will convert values with a string key into an array. So 1 => 'foo' would be 0 => 'foo', but 'foo' => 'bar' will end up as 'foo' => ['bar']. I really don't understand this behaviour.
Using string keys would help you out in this case, but after learning more about array_merge_recursive I decided to avoid this function when possible. After I asked this question someone filed it as a bug in it since PHP 7.0, since it works differently in PHP 5.x.
You want to keep the keys, while array_merge_resursive doesn't preserve integer keys, while it does for integer keys:
If the input arrays have the same string keys, then the values for
these keys are merged together into an array, and this is done
recursively, so that if one of the values is an array itself, the
function will merge it with a corresponding entry in another array
too. If, however, the arrays have the same numeric key, the later
value will not overwrite the original value, but will be appended.
To make it worse, it handles differently when handling the nested arrays:
$array1 = [30 => [500 => 'foo', 600 => 'bar']];
$array2 = [];
array_merge_recursive($array1, $array2);
//[0 => [500=> 'foo', 600 => 'bar']];
So effectively, array_merge_resursive isn't really resursive.
Using array_replace_resursive solves that problem:
array_replace_recursive($array1, $array2);
//output:
//array:5 [
// 1 => "22"
// "b" => 2
// 3 => 44
// 8 => 8
// 9 => 9
//]
Please note that PHP is very consistent in being inconsistent. While array_merge_recursive isn't recursive, array_replace_recursive doesn't replace (it also appends):
If the key exists in the second array, and not the first, it will be
created in the first array.
In many cases this is desired behavior and since naming functions isn't PHP's strongest point, you can consider this as a minor issue.
Can you rely on a native function to return your exact desired output? No. At least not in any version as of the date of this post (upto PHP8.1).
The good news is that crafting your own solution is very simple.
Code: (Demo)
foreach ($array2 as $key => $value) {
if (!key_exists($key, $array1)) {
$array1[$key] = $value;
} else {
$array1[$key] = (array)$array1[$key];
$array1[$key][] = $value;
}
}
var_export($array1);
I suppose I am less inclined to recommend this output structure because you have potentially different datatypes on a given level. If you were building subsequent code to iterate this data, you'd need to write conditions on every level to see if the data was iterable -- it just feels like you are setting yourself up for code bloat/convolution. I'd prefer a result which has consistent depth and datatypes.

What kind of array does PHP use?

I can define an array in PHP like this:
$array = array();
In C++, we have two kinds of array.
The first kind is a fixed size array, for example:
int arr[4]; // 4 ints, hardcoded size
The second kind is a dynamic sized array
std::vector<int> v; // can grow and shrink at runtime
What kind of array does PHP use? Are both kinds of arrays in PHP? If so, can you give me examples?
PHP is not as strict as C or C++. In PHP you don't need to specify the type of data to be placed in an array, you don't need to specify the array size either.
If you need to declare an array of integers in C++ you can do it like this:
int array[6];
This array is now bound to only contain integers. In PHP an array can contain just about everything:
$arr = array();
$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[] = 4;
var_dump($arr); //Prints [1,2,3,4]
$arr[] = 'hello world'; //Adding a string. Completely valid code
$arr[] = 3.14; //Adding a float. This one is valid too
$arr[] = array(
'id' => 128,
'firstName' => 'John'
'lastName' => 'Doe'
); //Adding an associative array, also valid code
var_dump($arr); //prints [1,2,3,4,'hello world',3.14, [ id => 128, firstName => 'John', lastName => 'Doe']]
If you're coming from a C++ background it's best to view the PHP array as a generic vector that can store everything.
From php.net
An array in PHP is actually an ordered map. A map is a type that
associates values to keys. This type is optimized for several
different uses; it can be treated as an array, list (vector), hash
table (an implementation of a map), dictionary, collection, stack,
queue, and probably more. As array values can be other arrays, trees
and multidimensional arrays are also possible.
Basically there are three Usage patterns of array in PHP.
Indexed array: Arrays with sequential numeric index, such as 0, 1, 2, etc. Example:
$myarray = array();
$myarray[0] = "test data 1";
$myarray[1] = "test data 2";
$myarray[3] = "test data 3";
Associative array: This is the most frequently used type of PHP arrays whose elements are defined in key/value pair. Example:
$myarray = array();
$myarray["key1"] = "value 1";
$myarray["key2"] = "value 2";
$myarray["key3"] = "value 3";
Multidimensional array: Arrays whose elements may contains one or more arrays. There is no limit in the level of dimensions. Example:
$myarray = array();
$myarray[0] = array("data01","data02","data03");
$myarray[1] = array("data11","data12","data13");
For more details - Refer to PHP 5 Arrays.
PHP uses three kinds of array:
Numeric array − An array with a numeric index. Values are stored and accessed in linear fashion.
Associative array − An array with strings as index. This stores element values in association with key values rather than in a strict linear index order.
Multidimensional array − An array containing one or more arrays and values are accessed using multiple indices.
Numeric Array Ex:
$numbers = array( 1, 2, 3, 4, 5);
Associative Array Ex:
$salaries = array("mohammad" => 2000, "qadir" => 1000, "zara" => 500);
Multidimensional Array Ex:
$marks = array(
"mohammad" => array (
"physics" => 35,
"maths" => 30,
"chemistry" => 39
),
"qadir" => array (
"physics" => 30,
"maths" => 32,
"chemistry" => 29
),
"zara" => array (
"physics" => 31,
"maths" => 22,
"chemistry" => 39
)
);
A php array, in C++ terms, is roughly:
std::map< std::experimental::any, std::experimental::any >
where std::experimental::any is a type that can hold basically anything. The php equivalent also can be sorted with the equivalent of <.
Well not quite -- closer to the truth is that a php array is an abstract interface that exposes much of the operations that the above map would provide in C++ (the C++ map is a concrete implementation).
Arrays with contiguous numeric keys stored in the Variant are treated much like a std::vector<Variant>, and under the interface the php system might even use vector<Variant> or something similar to store it, or even have two different internal details, one of which is for contiguous blocks of integer indexed data, and the other for sparse entries. (I don't know how php is implemented, but that is how I would do it)
PHP uses numeric, associative arrays, and multidimensional arrays. Arrays are dynamic in nature, and no size should be mentioned. Go through php.net/manual/en/language.types.array.php to find details.

Array Key cannot be accesed

I have a little problem with the key of an array.
The array looks like this:
Array
(
[1] => Array
(
["question"] => test question 1
["open_response"] => 1
)
[2] => Array
(
["question"] => test question 2
["yes_no"] => 1
)
)
But for some reason whenever I try to access $data['1']['question'] it tells me that question is not an index. I'm a little confused about this since it should be a key but is not, how can I fix this? or how can i access it?
You want:
$data[1]['question']
Not:
$data['1']['question']
Edit:
My answer doesn't solve his problem, rather it helped him find the actual issue. The two snippets above are exactly the same thing because PHP will cast string keys into integers if the string is a valid integer. IMO, its confusing as hell. If I key my array with a string, dag`nammit it should be keyed with a string even if that string can also be parsed into an int!
The relevant documentation can be found here:
The key can either be an integer or a string. The value can be of any type.
Additionally the following key casts will occur:
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.
Floats are also cast to integers, which means that the fractional part will be truncated. E.g. the key 8.7 will actually be stored under 8.
Bools are cast to integers, too, i.e. the key true will actually be stored under 1 and the key false under 0.
Null will be cast to the empty string, i.e. the key null will actually be stored under "".
Arrays and objects can not be used as keys. Doing so will result in a warning: Illegal offset type.
Where are your array providing from?
Array indexes may have nonvisible (by your editor, browser etc) chars like backspace or null (\0) character. You can not see theese chars on var_dump.
Look this example :
code :
<pre>
<?php
$a = array(
"\0question\0" => "test question 1",
"question\0" => "test question 2",
"\0question" => "test question 3",
"question" => "test question 4"
);
var_dump($a);
?>
Output :
array(4) {
["question"]=>
string(15) "test question 1"
["question"]=>
string(15) "test question 2"
["question"]=>
string(15) "test question 3"
["question"]=>
string(15) "test question 4"
}
you can use some array functions like : array_values, array_map to rebuil and validate your array.

Are there dictionaries in php?

For example:
$names = {[bob:27, billy:43, sam:76]};
and then be able to reference it like this:
$names[bob]
http://php.net/manual/en/language.types.array.php
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>
Standard arrays can be used that way.
There are no dictionaries in php, but PHP array's can behave similarly to dictionaries in other languages because they have both an index and a key (in contrast to Dictionaries in other languages, which only have keys and no index).
What do I mean by that?
$array = array(
"foo" => "bar",
"bar" => "foo"
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
The following line is allowed with the above array in PHP, but there is no way to do an equivalent operation using a dictionary in a language like Python(which has both arrays and dictionaries).
print $array[0]
PHP arrays also give you the ability to print a value by providing the value to the array
print $array["foo"]
Normal array can serve as a dictionary data structure. In general it has multipurpose usage: array, list (vector), hash table, dictionary, collection, stack, queue etc.
$names = [
'bob' => 27,
'billy' => 43,
'sam' => 76,
];
$names['bob'];
And because of wide design it gains no full benefits of specific data structure. You can implement your own dictionary by extending an ArrayObject or you can use SplObjectStorage class which is map (dictionary) implementation allowing objects to be assigned as keys.
Use arrays:
<?php
$arr = [
"key" => "value",
"key2" => "value2"
];
If you intend to use arbitrary objects as keys, you may run into "Illegal offset type". To resolve this you can wrap the key with the call of spl_object_hash function, which takes any object, and returns its unique hash.
One thing to keep in mind, however, is that then the key itself will be the hash, and thus you will not be able to get a list of the objects used to generate those hashes from your dictionary. This may or may not be what you want in the particular implementation.
A quick example:
<?php
class Foo
{
}
$dic = [];
$a = new Foo();
$b = new Foo();
$c = $a;
$dic[spl_object_hash($a)] = 'a';
$dic[spl_object_hash($b)] = 'b';
$dic[spl_object_hash($c)] = 'c';
foreach($dic as $key => $val)
{
echo "{$key} -> {$val}\n";
}
The output i get is:
0000000024e27223000000005bf76e8a -> c
0000000024e27220000000005bf76e8a -> b
Your hashes, and hashes at different executions may be different.

access array element by value

array(
[0]
name => 'joe'
size => 'large'
[1]
name => 'bill'
size => 'small'
)
I think i'm being thick, but to get the attributes of an array element if I know the value of one of the keys, I'm first looping through the elements to find the right one.
foreach($array as $item){
if ($item['name'] == 'joe'){
#operations on $item
}
}
I'm aware that this is probably very poor, but I am fairly new and am looking for a way to access this element directly by value. Or do I need the key?
Thanks,
Brandon
If searching for the exact same array it will work, not it you have other values in it:
<?php
$arr = array(
array('name'=>'joe'),
array('name'=>'bob'));
var_dump(array_search(array('name'=>'bob'),$arr));
//works: int(1)
$arr = array(
array('name'=>'joe','a'=>'b'),
array('name'=>'bob','c'=>'d'));
var_dump(array_search(array('name'=>'bob'),$arr));
//fails: bool(false)
?>
If there are other keys, there is no other way then looping as you already do. If you only need to find them by name, and names are unique, consider using them as keys when you create the array:
<?php
$arr = array(
'joe' => array('name'=>'joe','a'=>'b'),
'bob' => array('name'=>'bob','c'=>'d'));
$arr['joe']['a'] = 'bbb';
?>
Try array_search
$key = array_search('joe', $array);
echo $array[$key];
If you need to do operations on name, and name is unique within your array, this would be better:
array(
'joe'=> 'large',
'bill'=> 'small'
);
With multiple attributes:
array(
'joe'=>array('size'=>'large', 'age'=>32),
'bill'=>array('size'=>'small', 'age'=>43)
);
Though here you might want to consider a more OOP approach.
If you must use a numeric key, look at array_search
You can stick to your for loop. There are not big differences between it and other methods – the array has always to be traversed linearly. That said, you can use these functions to find array pairs with a certain value:
array_search, if you're there's only one element with that value.
array_keys, if there may be more than one.

Categories