PHP array as array key - php

Is it possible in php to make an array an array key as well?
Example:
array(
array('sample', 'abc') => 'sample value'
);

No, if you read the manual
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.
And :
The key can either be an integer or a string. The value can be of any type.

This is not possible - array keys must be strings or integers.
What you could do is use serialize:
$myArr = array( serialize(array('sample', 'abc')) => 'sample value');
Which will be the same as:
$myArr = array( 'a:2:{i:0;s:6:"sample";i:1;s:3:"abc";}' => 'sample value');
and could be accessed like:
echo $myArr[serialize(array('sample', 'abc'))];
But note that the serialised string which would be the unique identifier for the array item is clearly fairly complicated and almost impossible to type by hand.

PHP arrays can contain integer and string keys while since PHP does not distinguish between indexed and associative arrays.
Look for php manual Php Manual

whats wrong with
array(
'sample value' => array('sample', 'abc')
);
you could then do
foreach($array as $string => $child){
...
}
and use the $child for whatever purpose

Related

Restructure 2d array so that column values become row values (transpose but preserve first level keys)

The situation is as follows. I have a parent array which looks like the following:
$parent = [
1 => ['test1', 'test2'],
2 => ['test1_1', 'test2_2'],
];
I would like to group the data by column.
Desired result:
[
1 => ['test1', 'test1_1'],
2 => ['test2', 'test2_2'],
]
1 parent array called parent contains 2 arrays inside. I want to combine these two so that they have the same values as stated above. So this would mean that the arrays should be combined based on index number.
Since I do not make use of string keys, how would I accomplish this? I believe that there is no build in function available for this situation.
I would imagine that I could start beginning to create a new array and use a for loop through the parent array.
I tried the array-combine function however, this is NOT displaying the results I want.
[
1 => ['test1' => 'test1_1', 'test2' => 'test2_2'
]
If you need to preserve those first level keys, you can re-apply them after tranposing.
Code: (Demo)
var_export(
array_combine(array_keys($parent), array_map(null, ...$parent))
);
Otherwise, you can just transpose and accept the re-indexed first level keys. Honestly, I can't see any good reason to preserve the first level keys because by transposing, you remove the initial association between first level keys and the row values.
Code: (Demo)
var_export(
array_map(null, ...$parent)
);
If these techniques do not suit your actual project data, then we will need a more realistic sample array to be provided in your question body.
Loop over the keys of the top-level array. Then use the current index of the iteration to get the corresponding columns of the nested arrays.
$result = [];
foreach (array_keys($parent) as $i => $k) {
$result[$k] = array_column($parent, $i);
}
DEMO
This assumes the number of rows is the same as the number of columns. It's not clear what you expect the result to be if that's not true.

Can i use square brackets for declaring array variables in php [duplicate]

In CoffeeScript, Clojure, ES6 and many other languages we have destructuring of objects/maps/etc somewhat like this:
obj = {keyA: 'Hello from A', keyB: 'Hello from B'}
{keyA, keyB} = obj
I've found the list function in php which lets you destructure arrays like so:
$info = array('coffee', 'brown', 'caffeine');
list($drink, $color, $power) = $info;
Is there a way to destructure objects or associative arrays in PHP? If not in the core libs maybe someone wrote some smart helper function?
For PHP 7.0 and below that is beyond the functionality of list. The docs state:
list only works on numerical arrays and assumes the numerical indices start at 0.
One of the things that could suit your purpose would be the extract() function which imports variables from an array into the current symbol table. While with list you are able to define variable names explicitly, extract() does not give you this freedom.
Extracting an associative array
With extract you could do something like that:
<?php
$info = [ 'drink' => 'coffee', 'color' => 'brown', 'power' => 'caffeine' ];
extract($info);
var_dump($drink); // string(6) "coffee"
var_dump($color); // string(5) "brown"
var_dump($power); // string(8) "caffeine"
Extracting an Object
Extracting an object works almost the same. Since extract only takes an array as an argument we need to get the objects properties as an array. get_object_vars does that for you. It returns an associative array with all public properties as key and their values as value.
<?php
class User {
public $name = 'Thomas';
}
$user = new User();
extract( get_object_vars($user) );
var_dump($name); // string(6) "Thomas"
Pitfalls
extract() is not the same as list since it does not allow you to explicitly define the variable names that get exported to the symbol table. The variable names correspond the array keys by default.
list is a language construct while extract() is a function
It might happen that you overwrite variables that you have defined beforehand unintentionally
Your array keys might be invalid as variable names
With the $flags parameter that you can pass as second argument to extract() you can influence the behavior in case of colliding or invalid variables. But still it's important to know how extract() works and to use it with cauton.
Edit: As of PHP 7.1 this is possible:
http://php.net/manual/en/migration71.new-features.php#migration71.new-features.support-for-keys-in-list
You can now specify keys in list(), or its new shorthand [] syntax. This enables destructuring of arrays with non-integer or non-sequential keys.
https://php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring
The shorthand array syntax ([]) may now be used to destructure arrays for assignments (including within foreach), as an alternative to the existing list() syntax, which is still supported.
For example this:
$test_arr = ['a' => 1, 'b' => 2];
list('a' => $a, 'b' => $b) = $test_arr;
var_dump($a);
var_dump($b);
Will output the following as of 7.1.0
int(1)
int(2)
I noticed the accepted answer missed out examples that use the short-hand notation, security issues with using extract, and IDE issues.
Numerical Array Destructuring (PHP 7.1)
As of PHP 7.1 numerical array destructuring (Symetric array destructuring) is supported like so:
<?php
$data = [55, 'John', 'UK'];
[$id, $name] = $data; // short-hand (recommended)
list($id, $name) = $data; // long-hand
Notice that you can miss items out if you don't want them.
Associative Array Destructuring (PHP 7.1)
You can also destructure associative arrays (Support for keys in list) like so:
<?php
$data = ['id' => 55, 'firstName' => 'John', 'country' => 'UK']
['id' => $id, 'firstName' => $name] = $data; // short-hand (recommended)
list('id' => $id, 'firstName' => $name) = $data; // long-hand
Notice that you can miss items out if you don't want them. Also the variable name can be different to the property name.
Object Destructuring (PHP 7.1)
Unfortunately there is no object destructuring. However you can convert an object to an associative array using get_object_vars, and then use associative array destructuring.
<?php
class User {
public $id;
public $name;
public $country;
}
$user = new User();
$user->id = 55;
$user->name = 'John';
$user->country = 'UK';
['id' => $id, 'firstName' => $name] = get_object_vars($user)
However, this can break some IDE features. These are some issues I noticed when using PHPStorm 2019.1:
IDE's may no longer understand the type for the variables, so you would need to add some #var Type PHPDocs to maintain auto-complete functionality
Does not work well with refactoring tools. For example, if you rename one of the properties, the array destructuring portion will not also automatically rename.
So I recommend just doing it the normal way:
$id = $user->id
$name = $user->firstName
Do NOT use extract
With extract, all variables are always set. There it is a really bad idea to use it because:
It can lead to security issues. Even if your careful, it can lead to non-obvious security holes in the future. If you do use it, don't use it with user input (e.g. $_GET, $_POST), unless you want to make a malicious hacker's day.
Can lead to hard to detect bugs
If the class or array changes in the future, by introducing new properties, it can break your code if it coincides with an already used variable, unless you use the EXTR_SKIP flag or similar
Variable variables are one way to achieve this:
$args = ['a' => 1, 'b' => 2, 'c' => 3];
foreach (['a', 'c'] as $v) $$v = $args[$v];
// $a is 1, $b is undefined, $c is 3
It's really not pretty, and thankfully this has been addressed in 7.1 by https://wiki.php.net/rfc/short_list_syntax . This would let you say ['a' => $a, 'c' => $c] = $args; in the above example.
Since 7.1 includes a way to use a different name for your var than the assoc array key. This is pretty straight-forward using variable variables here too:
foreach (['a' => 'eh', 'b' => 'bee'] as $k => $v) $$v = $args[$k];
// $eh is 1, $bee is 2
Some developers, and some coding styles, define $$var as an anti-pattern similar to using eval, extract, and the GPR magic variables directly. This is because using variable variables makes code harder to understand, which leads directly to bugs and prevents static code analysis tools from functioning.
If you do adopt $$var, it can be helpful to use the ${$var} form instead, which makes it obvious that the author didn't simply type one too many $'s, and may spare the author immediate negative feedback when their code is audited.
One simple solution is to read the Object as an Array. So assuming you use #Yahya Uddin's User object, you can do like so:
['id' => $id, 'firstName' => $name] = (array)$user
// $id = 55, name = 'john'
This will tell PHP to read this objective as an associative Array.

Associative array of arrays

Ive come upon the following code and having trouble deciphering its use.
(changed up the variable names a bit for simplicity)
$fooo = array(
'dog' => array('pages', 'home'),
'cat' => array('users', 'login'),
'bird' => array('users', 'reset', 1),
);
I am familiar with associative arrays but have not seen this "nested array" implementation before.
Is this code creating an array of arrays?
For example, $fooo['dog'] returns an array where $dog[0]='pages' and $dog[1]='home'
That seems wrong.
Yes, this is an array of arrays. But it perhaps may be more accurate to describe it as an associative array with an indexed array for every value.
The following can be done with it:
$fooo['dog'] // gets array("pages", "home")
$fooo['bird'][0] // gets "users"
$fooo['cat'][1] // gets "login"
$fooo['cow'] = array('x', 'y'); // adds another value to the outer array
$fooo['bird'][] = 2; // $fooo['bird'] now equals array('users', 'reset', 1, 2)
There is nothing wrong with this code, but your example is lacking practicality. There is plenty of code that uses such structures though. For example, a logical representation of a menu with sub-menus on a website (which seems like the source of your sample), this data structure can then be looped to generate an HTML/CSS menu.

PHP Function with array_search Not working

I have a function using array_search not working ... here is my code
function LangFull($name){
$languageCodes = array(
"abkhazian"=>"ab",
"afar"=>"aa",
"afrikaans"=>"af",
"afrikaans"=>"af-za",
"zulu"=>"zu",
"zulu"=>"zu-za"
);
return ucwords(array_search(strtolower($name),$languageCodes));
}
echo LangFull("zu"); /// Gives no output
echo LangFull("zu-za"); /// Gives output
same with af is no output ... please help
If its possible to interchange, (values to keys and keys to values) and won't have those key collisions, then you can do it that way also:
function LangFull($name){
$languageCodes = array(
"ab" => "abkhazian",
"aa" => "afar",
"af" => "afrikaans",
"af-za" => "afrikaans",
"zu" => "zulu",
"zu-za" => "zulu",
);
return isset($languageCodes[$name]) ? ucwords(strtolower($languageCodes[$name])) : 'Not found';
}
echo LangFull("zu"); /// Gives output
echo LangFull("zu-za"); /// Gives output
echo LangFull("yahoo!");
You have two identical array keys:
"zulu"=>"zu",
"zulu"=>"zu-za"
You need to name one of them something else.
As they are the same, trying to access one of them specifically is futile as PHP does not know which of the two you are requesting.
Alternatively, if you are trying to store more than 1 data value for a given key, you can make the value of a key an array, so can then store more data as required.
e.g.
array (
"afrikaans"=> array(
"af",
"af-za",
),
"zulu"=> array(
"zu",
"zu-za",
)
);
EDIT.
In response to you asking about swapping the keys and values:
You can, and Ghost has shown you how.
However retaining your keys as they are (as my above array example) allows you to collate all relevant data into one index, and can access it easily.
Swapping values and keys will likely make it harder to obtain data you need, as your key is now the "data". So to grab data from an array you'd need to know the data (as it's now the key) and you'd actually be grabbing the reference (what was your key).
Which is a bit odd. It can work, but it's not really ideal.

Change position of elements in array

I have a simple question:
Query returns array in which I would like to change order of elements in PHP.
I have an array like this:
$typesSumAr = array( 'break', 'private absence', 'sick leave', 'vacation', 'work', 'work absence' );
I would like to have an array in this order:
$typesSumAr = array( 'work', 'break', 'sick leave', 'vacation', 'private absence', 'work absence' );
The are not always all elements in array, it could be only two for example, so I cannot hardcode the array. Do I need to make if statemenets to find out if key exists and then order it manually?
Thank you for your answer.
Seeing as you have an array in the order you prefer, your problem boils down to keeping the elements that are also present in another array. PHP has a function for exactly that: array_intersect
array_intersect returns an array containing all the values of its first array argument that are present in all the arguments. Note that keys are preserved.
There are lots of great array sorting function depending on how you want to sort it. Have a look here http://www.php.net/manual/en/array.sorting.php or even based on your own function via uksort (http://www.php.net/manual/en/function.uksort.php)

Categories