Here is the array
$anArray = array(
"theFirstItem" => "a first item",
if(True){
"conditionalItem" => "it may appear base on the condition",
}
"theLastItem" => "the last item"
);
But I get the PHP Parse error, why I can add a condition inside the array, what's happen??:
PHP Parse error: syntax error, unexpected T_IF, expecting ')'
Unfortunately that's not possible at all.
If having the item but with a NULL value is ok, use this:
$anArray = array(
"theFirstItem" => "a first item",
"conditionalItem" => $condition ? "it may appear base on the condition" : NULL,
"theLastItem" => "the last item"
);
Otherwise you have to do it like that:
$anArray = array(
"theFirstItem" => "a first item",
"theLastItem" => "the last item"
);
if($condition) {
$anArray['conditionalItem'] = "it may appear base on the condition";
}
If the order matters, it'll be even uglier:
$anArray = array("theFirstItem" => "a first item");
if($condition) {
$anArray['conditionalItem'] = "it may appear base on the condition";
}
$anArray['theLastItem'] = "the last item";
You could make this a little bit more readable though:
$anArray = array();
$anArray['theFirstItem'] = "a first item";
if($condition) {
$anArray['conditionalItem'] = "it may appear base on the condition";
}
$anArray['theLastItem'] = "the last item";
If you are making a purely associative array, and order of keys does not matter, you can always conditionally name the key using the ternary operator syntax.
$anArray = array(
"theFirstItem" => "a first item",
(true ? "conditionalItem" : "") => (true ? "it may appear base on the condition" : ""),
"theLastItem" => "the last item"
);
This way, if the condition is met, the key exists with the data. If not, it's just a blank key with an empty string value. However, given the great list of other answers already, there may be a better option to fit your needs. This isn't exactly clean, but if you're working on a project that has large arrays it may be easier than breaking out of the array and then adding afterwards; especially if the array is multidimensional.
Your can do it like this:
$anArray = array(1 => 'first');
if (true) $anArray['cond'] = 'true';
$anArray['last'] = 'last';
However, what you want is not possible.
Try this if you have associative array with different keys:
$someArray = [
"theFirstItem" => "a first item",
] +
$condition
? [
"conditionalItem" => "it may appear base on the condition"
]
: [ /* empty array if false */
] +
[
"theLastItem" => "the last item",
];
or this if array not associative
$someArray = array_merge(
[
"a first item",
],
$condition
? [
"it may appear base on the condition"
]
: [ /* empty array if false */
],
[
"the last item",
]
);
There's not any magic to help here. The best you can do is this:
$anArray = array("theFirstItem" => "a first item");
if (true) {
$anArray["conditionalItem"] = "it may appear base on the condition";
}
$anArray["theLastItem"] = "the last item";
If you don't care specifically about the order of the items, it gets a little more bearable:
$anArray = array(
"theFirstItem" => "a first item",
"theLastItem" => "the last item"
);
if (true) {
$anArray["conditionalItem"] = "it may appear base on the condition";
}
Or, if the order does matter and the conditional items are more than a couple, you can do this which could be considered more readable:
$anArray = array(
"theFirstItem" => "a first item",
"conditionalItem" => "it may appear base on the condition",
"theLastItem" => "the last item",
);
if (!true) {
unset($anArray["conditionalItem"]);
}
// Unset any other conditional items here
You can assign all values and filter empty keys from the array at once like this:
$anArray = array_filter([
"theFirstItem" => "a first item",
"conditionalItem" => $condition ? "it may appear base on the condition" : NULL,
"theLastItem" => "the last item"
]);
This allows you avoid the extra conditional after the fact, maintain key order, and imo it's fairly readable. The only caveat here is that if you have other falsy values (0, false, "", array()) they will also be removed. In that case you may wish to add a callback to explicitly check for NULL. In the following case theLastItem won't get unintentionally filtered:
$anArray = array_filter([
"theFirstItem" => "a first item",
"conditionalItem" => $condition ? "it may appear base on the condition" : NULL,
"theLastItem" => false,
], function($v) { return $v !== NULL; });
You can do it like this:
$anArray = array(
"theFirstItem" => "a first item",
(true ? "conditionalItem" : "EMPTY") => (true ? "it may appear base on the condition" : "EMPTY"),
"theLastItem" => "the last item"
);
unset the EMPTY array item if the condition is false
unset($anArray['EMPTY']);
Its pretty simple. Create array with essential elements. Then add conditional elements to the array. Now add other elements if required.
$anArray = array(
"theFirstItem" => "a first item"
);
if(True){
$anArray+=array("conditionalItem" => "it may appear base on the condition");
}
$more=array(
"theLastItem" => "the last item"
);
$anArray+=$more;
You modify this code to make it even more shorter,, i have just given elaborated code to make it self explantory. No NULL element, no empty string, put you item anywhere you want, no hassel.
You can use array_merge
$result = array_merge(
['apple' => 'two'],
(true ? ['banana' => 'four'] : []),
(false ? ['strawberry' => 'ten'] : [])
);
print_r($result);
// Output:
/*
Array
(
[apple] => 'two'
[banana] => 'four'
)
*/
Drawback of array_merge: Values in an array with numeric keys will be renumbered with incrementing keys starting from zero in the result array. You can use the union operator instead to maintain the original numeric keys
Or by using Array Union Operator
$result = ['apple' => 'two'] + (true ? ['banana' => 'four'] : []) + (false ? ['strawberry' => 'ten'] : []);
print_r($result);
// Output:
/*
Array
(
[apple] => 'two'
[banana] => 'four'
)
*/
Note: When using the union operator, remember that for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.
Related
I am aware that I could use a loop to answer my question, but I was hoping that maybe PHP has a function to do what I am trying to achieve and that someone might know.
Basically I am trying to identify a unique key from a series of arrays and then extract the value of the correlated key in the array.
So basically, from this array:
$myarray = array(array("id" => 1, "label" => "True"), array("id" => 2, "label" => "False"))
I want to be able to find the label value when the id is searched and matched, i.e. $id = 1 should return True.
Any simple functions available to do this without having to write a couple of loops?
It would be one simple loop. But if you are loopofobic, then you can rely on other functions (that acts as loop too):
function find(array $inputs, int $search): ?string
{
$result = array_filter($inputs, fn ($input) => $input['id'] === $search);
return current($result)['label'] ?? null;
}
$myarray = [["id" => 1, "label" => "True"], ["id" => 2, "label" => "False"]];
var_dump(find($myarray, 1)); // string(4) "True"
var_dump(find($myarray, 2)); // string(5) "False"
var_dump(find($myarray, 3)); // NULL
Live Example
you may use the built-in function array_column() for your aim.
$myarray = array(array("id" => 1, "label" => "True"), array("id" => 2, "label" => "False"));
/* label (value) per id (key) in 1-dimensional array.*/
print_r(array_column($myarray,'label','id'));
will return
Array
(
[1] => True
[2] => False
)
so you may adjust the code below.
$myarray = array(array("id" => 1, "label" => "True"), array("id" => 2, "label" => "False"));
$id_val = 1;
$output = isset(array_column($myarray,'label','id')[$id_val]) ? array_column($myarray,'label','id')[$id_val] : 'key not found';
var_dump($output);
I have this PHP array:
$this->user_list = array( 0 => 'Not paid',1 => 'Not paid', 2 => 'Not paid', 7 => 'Waiting, 15 => 'Waiting', 10 => 'Cancelled' );
How can I simplify this array as the id numbers are different, but some of them have same status?
I tried it like this:
$this->user_list = array( [0,1,2 => 'Not paid'],[7,15 => 'Waiting'],10 => 'Cancelled' );
but it doesn't work as expected.
Basically I want to achieve this:
echo $this->user_list[15] should give me Waiting, echo $this->user_list[10] should give me Cancelled, etc. So this is working in my first array very well, I am just thinking about grouping duplicate names there.
As mentioned by other contributors, there is no native support in the PHP grammar for your intended use case. As clearly stated in the PHP: Arrays documentation:
An array can be created using the array() language construct. It takes any number of comma-separated key => value pairs as arguments.
So basically each element in an array is a key => value pair, which means you cannot associate multiple keys to a single element.
This also explains why your first tentative didn't work:
$this->user_list = array( [0,1,2 => 'Not paid'],[7,15 => 'Waiting'],10 => 'Cancelled' );
If you don't specify a key for an element, PHP uses a progressive index (0, 1, ...). So basically in the example above, the first zero is not actually a key, but a value, and PHP binds it to the key = 0. Maybe it could be easier for you to understand how it works if you print a var_dump or print_r of $this->user_list. You would get something similar to the following structure (NOTE: I have simplified the structure to make it more clear):
[
0 => [
0 => 0
1 => 1
2 => "Not paid"
],
1 => [
0 => 7,
15 => "Waiting"
],
10 => "Cancelled"
]
So how do we resolve this problem? Well... actually there is no need to contort the structure by swapping keys with values as other contributors seem to suggest. Changing the structure might simplify your "data entry" work but might also create big issues in other parts of the program because who knows, maybe accessing the invoice data by "ID" is simply more efficient than by "status" ... or something.
Since PHP does not provide such a feature out of the box, I believe a better solution would be to develop our own function; a good starting point could be the one in the example below.
function explode_array($config, $sep = ',') {
$res = [];
foreach($config as $configKey => $value) {
// split key values
$keys = explode($sep, $configKey);
foreach($keys as $key) {
$res[$key] = $value;
}
}
return $res;
}
$config = [
'0,1,2' => 'Not paid',
'7,15' => 'Waiting',
'10' => 'Cancelled'
];
$myArr = explode_array($config);
print_r($myArr);
The idea is quite simple: since we cannot use an array as key we leverage the next best data type, that is a CSV string. Please note there is no error handling in the above code, so the first thing you may want to do is adding some validation code to the explode_array (or however you wish to name it) function.
you should use like this. if id number is invoice id or something else and other value is there status about it.
$arr = array(
'Not paid' => [0,1,2] ,
'Waiting' => [5,6],
'Cancelled' =>[8]
);
foreach($arr as $key => $val){
foreach($val as $keys => $vals){
echo "invoiceid ".$vals ." status ".$key;
echo"<br>";
}
}
// for only one status you can use like this
foreach($arr['Not paid'] as $key => $val){
echo $val;
echo"<br>";
}
just try to run this and check output.
PHP has no built-in function or structure for handling cases like this. I'd use a simple array value-cloning function to map your duplicates. Simply have one instance of each status, then map the aliases, and then run a function that clones them in. As follows:
// Status list:
$ulist = [ 0 => 'Not paid', 7 => 'Waiting', 10 => 'Cancelled' ];
// Alternative IDs list, mapped to above source IDs:
$aliases = [ 0 => [1,2], 7 => [15] ];
// Function to clone array values:
function clone_values(array &$arr, array $aliases)
{
foreach($aliases as $src => $tgts) {
foreach($tgts as $tgt) {
$arr[$tgt] = $arr[$src];
}
}
ksort($arr); // If the order matters
}
// Let's clone:
clone_values($ulist, $aliases);
This results in the following array:
array(6) {
[0] · string(8) "Not paid"
[1] · string(8) "Not paid"
[2] · string(8) "Not paid"
[7] · string(7) "Waiting"
[10] · string(9) "Cancelled"
[15] · string(7) "Waiting"
}
....which can be accessed as you expect, here $ulist[2] => Not paid, etc. If the use case is as simple as illustrated in the OP, I'd personally just spell it out as is. There's no dramatic complexity to it. However, if you have dozens of aliases, mapping and cloning begins to make sense.
As said in the comments, you can't have multiple keys with one value. The best way is to use the keyword => [ number, number, number...] construction.
//set a result array
$result = [];
//loop the original array
foreach ( $this->user_list as $number => $keyword ){
//if the keyword doesn't exist in the result, create one
if(!isset ( $result [ $keyword ] ) ) $result[ $keyword ] = [];
//add the number to the keyword-array
$result[ $keyword ] [] = $number;
}
For this nested array:
$status = array(
"house" => "OK",
"car" => array(
"car1" => "OK",
"car2" => "ERROR"
),
"boat" => "OK"
);
I want to know if a certain value "ERROR" exists at least once in the array. I don't care what key it's associated with, I just want to know if the $status array contains an "ERROR" status anywhere in it.
Is there a cleaner way to do this than just iterating over the elements with nested for loops?
You could use the function array_walk_recursive() to get all the values with any level of nested array.
https://secure.php.net/manual/en/function.array-walk-recursive.php
<?php
$status = array(
"house" => "OK",
"car" => array(
"car1" => "OK",
"car2" => "OK"
),
"boat" => "OK"
);
$required = array();
array_walk_recursive($status, function ($value, $key) use (&$required){
$required[] = $value;
}, $required);
print '<pre>';
print_r($required);
print '</pre>';
?>
Output:
Array
(
[0] => OK
[1] => OK
[2] => OK
[3] => OK
)
I actually wouldn't use array recursive. It falls short in a few key things you want to do. And while at first it may seem like a "shortcut" to what you want,if fails in a few key ways:
you can't return a simple testable value like a boolean true of false from the callback in it.
you can't build the $all array with nesting, because the keys that have an array as their value are never passed to the callback. This essentially flattens the array out.
it's not portable, or in other words it's not reusable as it's procedural in nature.
That said, honestly I wouldn't build the all array because it's pointless as you already have that array, so there is no point copying it. As I said I don't think you really want to rebuild $all but if you did you couldn't do it with array_walk_recursive even if you wanted to...
Anyway.
$array = ['zero','one', 'two' => ['zoo' => 'foo']];
function checkRecursive($value, $array){
$x = false;
foreach($array as $v){
if(is_array($v)) $x = checkRecursive($value, $v); //recursive
if($v == $value || $x == true) return true;
}
return false;
}
echo checkRecursive('one', $array) ? "true\n" : "false\n";
echo checkRecursive('foo', $array) ? "true\n" : "false\n";
echo checkRecursive('bar', $array) ? "true\n" : "false\n";
prints
true
true
false
Test it
http://sandbox.onlinephpfunctions.com/code/78d0de421475b8e3104376c698027107e9b7e948
UPDATE
I see you changed the question and while you say "value" your array says the "key"
$status = array(
"house" => "OK",
"car" => array(
"car1" => "OK",
"car2" => "OK"
),
"boat" => "OK"
);
Because all the values are the same. So if you really want to find the key instead then just change it to this
function checkRecursive($value, $array){
$x = false;
foreach($array as $k=>$v){
if(is_array($v)) $x = checkRecursive($value, $v); //recursive
if((string)$value == (string)$k || $x == true) return true;
}
return false;
}
A few things to note when checking for the keys, it's possible they will not always be strings, or that you will check using an unqoted number. In these cases PHP sometimes has a weird way of changing a string into an integer and non-numeric strings will come out as 0. For example "1" = 1 but "one" = 0 when taken as an integer. Therefore if you have an array with a key of 0 and you check for one it will match it because it will turn "one" into a 0.
You can solve this by casting everything to strings. Or by using the === strict type checking. I prefer the string method because checking with === would make 0 != "0" so if you tried finding a key of 0 with "0" it would say no match. This is true of other numbers. That is unless you plan on checking objects with it.
This is still an issue when looking for the "values" but it's less of one, because there you are not dealing with the native integer keys in an array, so there is a greater possibility you wouldn't encounter it.
It all has to do with PHP's loosely typed nature, it's a feature not a bug...
I put this small example togather:
echo '(int)"one": ';
echo (int)"one";
echo "\n";
echo "0 == 'one': " . (0 == "one" ? "true\n" : "false\n");
echo "1 == '1': " . (1 == "1" ? "true\n" : "false\n");
Outputs:
(int)"one": 0
0 == 'one': true
1 == '1': true
http://sandbox.onlinephpfunctions.com/code/df41f55251570a12d9ca693712bcdc785ad62f85
I have an input:
$url = $params[0];
I have an array:
$dictionary = array(
"stock" => 1,
"user" => 2,
"zone" => 3);
How can I use the input to search the left values of this array (stock, user, zone, etc.) and get back the value on the right (1, 2, 3, etc.)?
Pretty simple, just access it like this
$dictionary[$url]
You can use this $url variable as a key to get the => value associated with it.
$dictionary = array(
"stock" => 1,
"user" => 2,
"zone" =>3);
$url = $params[0];
$yourDesiredValue = $dictionary[$url];
Since you are searching, you will want to check if the value (I presume $url) is set within the array and return it if true.
$value = false;
if (isset($dictionary[$url])) {
$value = $dictionary[$url];
}
Then, $value will be false if the search fails, but contain the number if the search is successful.
I have a COLLECTION collflokks in MongoDB, sample Document is :-
{
"_id" : "b_8AUL",
"f_name" : "Pizza. Hut",
"f_lat" : "22.7523513",
"f_lng" : "75.9225847",
"c_uid" : "33",
"f_type" : NumberLong(3),
"members" : [
"42",
"43"
]
}
Within the "members" array , I want to add Arrays like {id:42,name:Mark} , {id:43,name:Hughes}
Currently i'm adding just ids(eg.42,43). I'm only concerned about the new data as it will have new ids .Please suggest.
Earlier I was using this code to push into the members Array:
$flokkCollection = 'collFlokks';
$flokkCollection->update(
array("_id" => $f_handle),
array('$push' => array("members" => $u_id))
);
Well if what you are asking here is "replacing your existing data" then you need to "loop" the results from the collection and "replace" the array content that exists with your new format.
There are likely smarter ways to approach this, but you are not really giving us all the required information in your question, so I can only answer in the basic terms.
Presuming you have:
$required = array(
array(array("id" => "42"), array("name" => "Mark")),
array(array("id" => "43"), array("name" => "Hughes"))
);
As input, then you do something like this:
function myMapper($v) {
return $v["id"];
}
$mapped = array_map("myMapper",$required);
foreach( $mapped as $value) {
$filtered = array_values(
array_filter($required,function($k) {
return $k["id"] == $value;
})
)[0];
collection.update(array(
array("members" => $value),
array('$set' => array(
"members.$" => $filtered
))
));
}
Which should use the positional $ operator to find the matched "position" of the array element by the value used in the "query" portion of the update statement, then in the "update" portion of that statement $set that current array index to the new value at the "filtered" content index from the original input array.
Outside of PHP. We call these inner elements "objects" and not "arrays" which is a PHP notation trait. Key/value things are "objects" and "lists" are "arrays".