I know how to get all array keys starting with a particular string in a single array >> How to get all keys from a array that start with a certain string?
But what would be the way to go for multidimensional arrays?
For instance, how to find all keys starting with 'foo-' in:
$arr = array('first-key' => 'first value'.
'sceond-key' => 'second value',
array('foo-1' => 'val',
'bar'=> 'value',
'foo-2' => 'val2')
);
Many thanks, Louis.
You can still apply the solution from the linked question, but with an additional outer filter.
$outputArray = array_filter(
$inputArray,
function ($element) {
return ! is_array($element)
|| ! empty(
array_filter($element, function($key) {
return strpos($key, 'foo-') === 0;
}, ARRAY_FILTER_USE_KEY)
);
}
);
See https://3v4l.org/NsgpR for working code.
PHP Manual: is_array()
Related
I have a fairly easy issue where I need to see if an associative array of arrays is empty in php. My array looks like this:
array (
'person1' =>
array (
),
'person2' =>
array (
),
'person3' =>
array (
),
)
In my case, the three array's for the three people holds nothing so I need a test whether this is empty. I have done this which works:
if ( empty($form_values['person1']) && empty($form_values['person2']) && empty($form_values['person3'] ) ){
echo 'values empty!!';
}
But I was hoping something a bit more cleaner with using empty like the following:
if (empty( $form_values )) {
echo 'HI!';
}
You can use array_filter() to filter all of the empty array elements. You can then use empty to check if the result is empty then.
I've shorthanded the arrays so it's a easier to read since the arrays are empty. array() will work the same.
$form_values = [
'person1' => [],
'person2' => [],
'person3' => []
];
if (empty(array_filter($form_values))) {
// empty
} else {
// not empty
}
If you're looking for a one-liner then you could do something like:
$form_values = array (
'person1' =>
array (
),
'person2' =>
array (
),
'person3' =>
array (
),
);
if(array_sum(array_map(function($v){return !empty($v);}, $form_values)) === 0)
{
// empty
}
else
{
// not empty
}
Use a loop that tests each nested array. If none of them are non-empty, the whole array is empty.
$is_empty = true;
foreach ($form_values as $val) {
if (!empty($val)) {
$is_empty = false;
break;
}
}
<?php
$data =
[
'pig' => [],
'hog' => [],
'sow' => []
];
$all_empty = array_filter($data) === [];
var_dump($all_empty);
Output:
bool(true)
From the manual for array_filter:
If no callback is supplied, all empty entries of array will be
removed. See empty() for how PHP defines empty in this case.
Note that if an item was deemed as empty, like an empty string, it would still return true. This test may not be strict enough.
More explicitly:
if (array_filter($data, function($v) {return $v !== []; }) === []) {}
Filter out all items that aren't the empty array. What we'll be left with is an empty array if all items are an empty array.
Or search and compare:
if (array_keys($data, []) == array_keys($data)) {}
Check keys belonging to items containing the empty array match the keys of the array. Or rather all items (if they exist) are the empty array.
Note that an empty array will also satisfy the three solutions above.
This question already has answers here:
How to get an array of specific "key" in multidimensional array without looping [duplicate]
(4 answers)
Closed 1 year ago.
I have a multidimensional array, that has say, x number of columns and y number of rows.
I want specifically all the values in the 3rd column.
The obvious way to go about doing this is to put this in a for loop like this
for(i=0;i<y-1;i++)
{
$ThirdColumn[] = $array[$i][3];
}
but there is an obvious time complexity of O(n) involved here. Is there a built in way for me to simply extract each of these rows from the array without having to loop in.
For example (this does not work offcourse)
$ThirdColumn = $array[][3]
Given a bidimensional array $channels:
$channels = array(
array(
'id' => 100,
'name' => 'Direct'
),
array(
'id' => 200,
'name' => 'Dynamic'
)
);
A nice way is using array_map:
$_currentChannels = array_map(function ($value) {
return $value['name'];
}, $channels);
and if you are a potentate (php 5.5+) through array_column:
$_currentChannels = array_column($channels, 'name');
Both results in:
Array
(
[0] => Direct
[1] => Dynamic
)
Star guests:
array_map (php4+) and array_column (php5.5+)
// array array_map ( callable $callback , array $array1 [, array $... ] )
// array array_column ( array $array , mixed $column_key [, mixed $index_key = null ] )
Is there a built in way for me to simply extract each of these rows from the array without having to loop in.
Not yet. There will be a function soon named array_column(). However the complexity will be the same, it's just a bit more optimized because it's implemented in C and inside the PHP engine.
Try this....
foreach ($array as $val)
{
$thirdCol[] = $val[2];
}
Youll endup with an array of all values from 3rd column
Another way to do the same would be something like $newArray = array_map( function($a) { return $a['desiredColumn']; }, $oldArray ); though I don't think it will make any significant (if any) improvement on the performance.
You could try this:
$array["a"][0]=10;
$array["a"][1]=20;
$array["a"][2]=30;
$array["a"][3]=40;
$array["a"][4]=50;
$array["a"][5]=60;
$array["b"][0]="xx";
$array["b"][1]="yy";
$array["b"][2]="zz";
$array["b"][3]="aa";
$array["b"][4]="vv";
$array["b"][5]="rr";
$output = array_slice($array["b"], 0, count($array["b"]));
print_r($output);
I am new to using multidimensional arrays with php, I have tried to stay away from them because they confused me, but now the time has come that I put them to good use. I have been trying to understand how they work and I am just not getting it.
What I am trying to do is populate results based on a string compare function, once I find some match to an 'item name', I would like the first slot to contain the 'item name', then I would like to increment the priority slot by 1.
So when when I'm all done populating my array, it is going to have a variety of different company names, each with their respective priority...
I am having trouble understanding how to declare and manipulate the following array:
$matches = array(
'name'=>array('somename'),
'priority'=>array($priority_level++)
);
So, in what you have, your variable $matches will point to a keyed array, the 'name' element of that array will be an indexed array with 1 entry 'somename', there will be a 'priority' entry with a value which is an indexed array with one entry = $priority_level.
I think, instead what you probably want is something like:
$matches[] = array(name => 'somename', $priority => $priority_level++);
That way, $matches is an indexed array, where each index holds a keyed array, so you could address them as:
$matches[0]['name'] and $matches[0]['priority'], which is more logical for most people.
Multi-dimensional arrays are easy. All they are is an array, where the elements are other arrays.
So, you could have 2 separate arrays:
$name = array('somename');
$priority = array(1);
Or you can have an array that has these 2 arrays as elements:
$matches = array(
'name' => array('somename'),
'priority' => array(1)
);
So, using $matches['name'] would be the same as using $name, they are both arrays, just stored differently.
echo $name[0]; //'somename';
echo $matches['name'][0]; //'somename';
So, to add another name to the $matches array, you can do this:
$matches['name'][] = 'Another Name';
$matches['priority'][] = 2;
print_r($matches); would output:
Array
(
[name] => Array
(
[0] => somename
[1] => Another Name
)
[priority] => Array
(
[0] => 1
[1] => 2
)
)
In this case, could this be also a solution with a single dimensional array?
$matches = array(
'company_1' => 0,
'company_2' => 0,
);
if (isset($matches['company_1'])) {
++$matches['company_1'];
} else {
$matches['company_1'] = 1;
}
It looks up whether the name is already in the list. If not, it sets an array_key for this value. If it finds an already existing value, it just raises the "priority".
In my opinion, an easier structure to work with would be something more like this one:
$matches = array(
array( 'name' => 'somename', 'priority' => $priority_level_for_this_match ),
array( 'name' => 'someothername', 'priority' => $priority_level_for_that_match )
)
To fill this array, start by making an empty one:
$matches = array();
Then, find all of your matches.
$match = array( 'name' => 'somename', 'priority' => $some_priority );
To add that array to your matches, just slap it on the end:
$matches[] = $match;
Once it's filled, you can easily iterate over it:
foreach($matches as $k => $v) {
// The value in this case is also an array, and can be indexed as such
echo( $v['name'] . ': ' . $v['priority'] . '<br>' );
}
You can also sort the matched arrays according to the priority:
function cmp($a, $b) {
if($a['priority'] == $b['priority'])
return 0;
return ($a['priority'] < $b['priority']) ? -1 : 1;
}
usort($matches, 'cmp');
(Sourced from this answer)
$matches['name'][0] --> 'somename'
$matches['priority'][0] ---> the incremented $priority_level value
Like David said in the comments on the question, it sounds like you're not using the right tool for the job. Try:
$priorities = array();
foreach($companies as $company) {
if (!isset($priorities[$company])) { $priorities[$company] = 0; }
$priorities[$company]++;
}
Then you can access the priorities by checking $priorities['SomeCompanyName'];.
There is many - good and less good - ways to check associative arrays, but how would you check a "fully associative" array?
$john = array('name' => 'john', , 8 => 'eight', 'children' => array('fred', 'jane'));
$mary1 = array('name' => 'mary', 0 => 'zero', 'children' => array('jane'));
$mary2 = array('name' => 'mary', 'zero', 'children' => array('jane'));
Here $john is fully associative, $mary1 and $mary2 are not.
To make it short, you can't because every array is implemented the same way. From the docs:
An array in PHP is actually an ordered map. A map is a type that associates values to keys.
If have no insight in the implementation, but I'm pretty sure that array(1,2,3) is just shorthand for array(0=>1, 1=>2, 2=>3), i.e. in the end it is exactly the same. There is nothing with which you could distinguish that.
You could only assume that arrays created via array(value, value,...) have an index with 0 and the others have not. But you have already seen that this must not always be the case.
And every attempt to detect an "associative" array would fail at some point.
The actual question is: Why do you need this?
Is this what you're looking for?
<?php
function is_assoc( $array ) {
if( !is_array( $array ) || array_keys( $array ) == range( 0, count( $array ) - 1 ) ) {
return( false );
}
foreach( $array as $value ) {
if( is_array( $value ) && !is_assoc( $value ) ) {
return( false );
}
}
return( true );
}
?>
The detection depends on your definition of associative. This function checks for the associative that means arrays that don't have sequential numeric keys. Some may say that associative is anything where the key was implicitly set instead of calculated by php. Others may even define all PHP arrays as associative (in which case is_array() would have sufficed). Again, it all depends, but this is the function I use in my projects. Hopefully, it's good enough for you.
I have one array that contains some settings that looks like basically like this:
$defaults = array(
'variable' => 'value',
'thearray' => array(
'foo' => 'bar'
'myvar' => array('morevars' => 'morevalues');
);
);
On another file, i get a string with the first level key and it's childs to check if there is a value attached to it. Using the array above, i'd get something like this:
$option = "thearray['myvar']['morevars']";
I need to keep this string with a similar format to the above because I also need to pass it to another function that saves to a database and having it in an array's format comes in handy.
My question is, having the array and the string above, how can i check for both, existance and value of the given key inside the array? array_key_exists doesn't seem to work below the first level.
You could use a simple function to parse your key-string and examine the array like:
function array_deep_exists($array, $key)
{
$keys = preg_split("/'\\]|\\['/", $key, NULL, PREG_SPLIT_NO_EMPTY);
foreach ($keys as $key)
{
if ( ! array_key_exists($key, $array))
{
return false;
}
$array = $array[$key];
}
return true;
}
// Example usage
$defaults = array(
'variable' => 'value',
'thearray' => array(
'foo' => 'bar',
'myvar' => array('morevars' => 'morevalues')
)
);
$option = "thearray['myvar']['morevars']";
$exists = array_deep_exists($defaults, $option);
var_dump($exists); // bool(true)
Finally, to get the value (if it exists) return $array where the above returns true.
Note that if your array might contain false, then when returning the value you'll have to be careful to differentiate no-matching-value from a successful false value.
You need to eval this code, and use isset function in an eval string, and don't forget to add $ character in right place before code eval
example:
eval("echo isset(\$defaults['varname']['varname2']);")
this will echo 0 or 1 (false or true) You can do anything in eval, like a php source