1

I am wondering if it is possible to append "nothing" to an array, i.e. the array won't be affected. The scenario is that I would like to use the ? : operators to append values to an array if it exists. Otherwise nothing should be appended. I am aware that I can solve this with an ordinary if statement without the else part. But is there a way to tell PHP that it should append "nothing"? I'm just curious if there's a method for this?

<?php
$source_arr = ["Car" => "Volvo", "City" => "Stockholm", "Country" => "Sweden"];
$new_arr    = [];

$new_arr[] = (key_exists("Car",   $source_arr)) ? $source_arr["Car"]   : [];
$new_arr[] = (key_exists("State", $source_arr)) ? $source_arr["State"] : [];  
// An ordinary if statement works of course:
// if (key_exists("State", $source_arr)) { $new_arr[] = $source_arr["State"]; }
// But, is it possible to use ? : and append "nothing" (i.e. not using []) if key doesn't exist?

echo "<pre>";
var_export($new_arr);
echo "</pre>";

// The above outputs (and I understand why):
//   array (
//    0 => 'Volvo',
//    1 => 
//    array (
//    ),
//  )
// 
// But I want the following result (but I don't know if it's possible with ? :)
//   array (
//     0 => 'Volvo',
//   )

?>
Gowire
  • 1,046
  • 6
  • 27
  • `if key_exists(...) { $new_arr[] = ... }`? – mousetail Dec 14 '22 at 17:44
  • 1
    @mousetail *"An ordinary if statement works of course:"* - They know that. Their question is asking about using a ternary `? ... : ...` instead of an `if` statement. – Tim Lewis Dec 14 '22 at 17:45
  • 1
    @mousetail Yes, I am aware of that as I mentioned in the question :) – Gowire Dec 14 '22 at 17:45
  • 1
    @Gowire since you started the line as `$new_arr[] = ...`, it will _always_ append something. But if the code after `?` is `$new_arr[] = ...`, then it will only append if the condition before `?` is `true`. `key_exists('Car', $source_arr) ? $new_arr[] = $source_arr["Car"] : null` – Tim Lewis Dec 14 '22 at 17:48
  • 1
    I'm struggling to see how trying to solve something like this when the simplest and most obvious solution is to us an `if` statement. – Nigel Ren Dec 14 '22 at 17:54
  • 2
    @NigelRen I don't think there's anything wrong with questions asking "can I do this ...", so long as they show an attempt. In this case, it was very close, just had to shuffle the code around a bit. I do also agree that an `if()` statement (or one of the answers below) is a better approach, but that's beside the point, right? – Tim Lewis Dec 14 '22 at 18:07
  • There is a very good comment about this on https://stackoverflow.com/questions/20053257/if-without-else-ternary-operator "The ternary operator is not equivalent to if/else. It's actually an expression that has to have a value." – user1915746 Dec 14 '22 at 18:53
  • 1
    @TimLewis How are those counterexamples? `null` is a value. – Barmar Dec 14 '22 at 22:06
  • What you're trying to do seems poorly designed. It's weird to have an indexed array whose elements are heterogenous and can be optional. If you don't add a value for `Car` to the array, how wil you know what the first element in the new array represents? – Barmar Dec 14 '22 at 22:09
  • [conditionally adding a element in a array](https://stackoverflow.com/q/6477903/2943403) and [A conditional element inside an array(...) construct](https://stackoverflow.com/q/4118875/2943403) – mickmackusa Dec 15 '22 at 01:24

4 Answers4

1

You can't do it when assigning to $array[]. You can do it with a function that takes an array argument, by wrapping the value to be added in an array, and using an empty array as the alternate value. array_merge() is such a function.

$new_array = array_merge($new_array, 
    key_exists("Car", $source_arr) ? [$source_arr["Car"]] : [],
    key_exists("State", $source_arr) ? [$source_arr["State"]] : []
);
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Even better, get everything in one line using array_intersect_key

$source_arr = ["Car" => "Volvo", "City" => "Stockholm", "Country" => "Sweden"];
$new_arr    = array_intersect_key($source_arr, ['Car'=>'','State'=>'']);

var_export($new_arr);

The above outputs the following:

array (
  'Car' => 'Volvo',
)

If you really do want a non-associative, indexed array, just pass the result of array_intersect_key to array_values:

$new_arr = array_values(array_intersect_key($source_arr, ['Car'=>'','State'=>'']));
array (
  0 => 'Volvo',
)

Check both methods here.

Arleigh Hix
  • 9,990
  • 1
  • 14
  • 31
  • The intended result is an indexed array, not an associative array. But it seems misguided to me, since indexed arrays should normally be homogeneous. – Barmar Dec 14 '22 at 22:04
  • @Barmar yes, thanks I missed that detail probably because it made no sense – Arleigh Hix Dec 14 '22 at 22:35
0

Yes, you absolutely can "push nothing" conditionally.

Use the splat operator to unpack an array with zero or one element in it.

Code: (Demo)

$source_arr = ["Car" => "Volvo", "City" => "Stockholm", "Country" => "Sweden"];
$new_arr    = [];

array_push(
    $new_arr,
    ...key_exists("Car",   $source_arr) ? [$source_arr["Car"]] : [],
    ...key_exists("State", $source_arr) ? [$source_arr["State"]] : []
);

var_export($new_arr);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
-1

You could always add the new value (i.e., even if it's empty) and then remove the empties with array_filter() when you're done adding:

$new_arr = array_filter([
    $source_arr["Car"] ?? null,
    $source_arr["State"] ?? null,
]);

Of course, the problem here is that you'll never be able to rely on what's in the array. Is the first element car? Is it city? Country? You'll never know.

Alex Howansky
  • 50,515
  • 8
  • 78
  • 98
  • Not to nitpick but this will generate a different output than using an `if (key_exists...` in the event that the key *does exist* but contains a falsey value. With your code, if `source_arr["State"] == 0` it will not get appended. That's probably what the OP wants anyway but it's good for a beginner to bear in mind. – But those new buttons though.. Dec 14 '22 at 18:58
  • @EatenbyaGrue I think you're confusing `??` with `?:` – Barmar Dec 14 '22 at 22:04
  • 1
    @Barmar - no. In this answer if `$source_arr["Car"] == 0` it will get filtered out and removed. That's what `array_filter()` does without an explicit callback - anything falsey gets removed. – But those new buttons though.. Dec 14 '22 at 22:13
  • Right, I was focusing just on the use of the null-coalescing operator. However, the OP's data seems to be strings, so this is probably moot. – Barmar Dec 14 '22 at 22:15