unset() in multidimensional array check if key exists first - php

My array:
$array = array(
'test' => 'hello',
'something' => array(
'sub1' => 'foo'
)
);
I'd like to use:
if(array_key_exists('sub1', $array['something'])
{
unset($array['something']['sub1'];
}
The unset part works, but the if statement returns false while the sub1 item is definitely there. Why is this?

I think you need to reformat your code a little. However, here is the formatted code,
$arr = [
'test' => 'hello',
'something' => [
'sub1' => 'foo'
]
];
if(
is_array($arr['something']) &&
array_key_exists('sub1', $arr['something'])
)
{
unset($arr['something']['sub1']);
}
print_r($arr);
and I am getting following result,
Array
(
[test] => hello
[something] => Array
(
)
)
Can you elaborate on what is it that you want to do ??

Related

Get certain elements of an array by its key

I'm sure there's a function for this:
What I have:
$myArray = array( 'foo' => 123, 'bar' => 456, 'lou' => 789, 'wuh' => 'xyz' );
$iNeed = array( 'foo', 'lou' );
How can I get the key value pairs that $iNeed:
$output = super_magic_function( $iNeed, $myArray );
// output should be array( 'foo' => 123, 'lou' => 789 );
How is that super_magic_function called (native php if possible)
$output = array_intersect_key($myArray, array_flip($iNeed));
If you need it as a function:
function super_magic_function($array, $required) {
return array_intersect_key($array, array_flip($required));
}
Output:
Array
(
[foo] => 123
[lou] => 789
)
Documentation: array_intersect_key(), array_flip()
Demo.

Flatten indexed array

I'm trying to insert a PHP array into a mysql database, but am having trouble with this particular array. I'm trying to create a function that takes
array( 0 => array ( 'col1' => 'value', 'col2' => 'value', 'col3' => 'value', 'col4' => value', 'col5' => 'value', 'col6' => array ( 'string' => array ( 'col7' => 'value' , 'col8' => 'value'), ), ),
1 => array ( 'col1' => 'value', 'col2' => 'value', 'col3' => 'value', 'col4' => array ( ), 'col5' => 'value', 'col6' => array ( 'string' => array ( ), ), ),
2 => array ( 'col1' => 'value', 'col2' => 'value', 'col3' => 'value', 'col4' => array ( ), 'col5' => 'value', 'col6' => array ( 'string' => array ( ), ), ), )
and seperates each numbered array and formats it as:
array( 'col1' => 'value', 'col2' => 'value', 'col3' => 'value', 'col4' => 'value', 'col5' => 'value', ['col6' => 'value','col7' => 'value',] )
array( 'col1' => 'value', 'col2' => 'value', 'col3' => 'value', 'col4' => 'value', 'col5' => 'value', ['col6' => 'value','col7' => 'value',] )
array( 'col1' => 'value', 'col2' => 'value', 'col3' => 'value', 'col4' => 'value', 'col5' => 'value', ['col6' => 'value','col7' => 'value',] )
depending on how many rows there are. Keep in mind these conditions:
+8 cols is just an example, the range can fluctuate greatly.
+Cols containing a array must be non existent if it empty, like in [1] and [2], but not [0].
+Any column could contain a empty or full array. if it contains a full array, it needs to be flatten while retaining it's value.
+Some arrays might have greater then 2 nested arrays. (elements)
+Not all of the arrays have nested arrays, they are already formatted correctly. These arrays can not be affected by the PHP function i'm trying to create.
I'm stumped, every function I've created has failed. Thanks everyone in advance.
UPDATE I used Var_export with this function to get the array above.
function flatten($array, $preserve_keys = false)
{
if (!$preserve_keys) {
$array = array_values($array);
}
$flattened_array = array();
foreach ($array as $k => $v) {
$flattened_array[$k] = $v;
if (is_array($v)) {
$flattened_array = array_merge($flattened_array, call_user_func(__FUNCTION__, $v, $preserve_keys));
} elseif ($preserve_keys) {
$flattened_array[$k] = $v;
} else {
$flattened_array[] = $v;
}
}
return (array)$flattened_array;
}
What you need is what's called a recursive function (see this question for more info: What is a RECURSIVE Function in PHP?).
Also it seems that each "col" in the array is a string (and not a number).
What you might want to try is check whether the first (or any) key in the array is numeric.
The code would look something like this:
public function extractArray($myArray){
$extractedArray = array(); // create a new array where all the flattened data will go
$arrayKeys = array_keys($myArray); // grab all the keys from the array
if (is_numeric($arrayKeys[0])): // if the first key is a number (it's nested)
$extractedArray = $myArray[0]; // remove one level of the array by grabbing everything from the first element
extractArray($extractedArray); // run our function again to check if we need to remove another layer
else:
$extractedArray = $myArray; // seems like there are no layers that need to be removed
endif;
return $extractedArray;
}
Edit:
Here is a possible solution for the second part of the problem (extracting values from possible sub-arrays)
Here are the steps we are going to take:
1) Loop through each element in our $extractedArray (from part 1) and see if it is a sub array
2) If it is an array we extract it's contents and place it in a temporary variable (an array for now)
3) We then call ourselves again (recursively) passing it the new temporary variable (until there are no more sub-arrrays left
4) Once we have extracted all the values and flattened them in to a single array, we can then loop through that array and store them as a string (or whatever else we like)
Updated Code
Here is the code:
public function flattenArrayValues($extractedArray){
$extractedValues = array();
foreach($extractedArray as $key => $eA):
if(is_array($eA)): // check whether current element is an array
reset($eA); // go to the first element of the array and grab it
$first_key = key($eA); // ...
$extractedValues[$key] = $eA[$first_key]; // this allows us to preserve the "cols" for each element
flattenArrayValues($extractedValues); //call ourselves again to check whether there are any sub-arrays
endif;
endforeach;
return $extractedValues; // seems like we extracted all the values and flattened them
// if we want we can loop through this new array and build a string out of it etc.
}
Hope this was helpful

PHP: how to create associative array by key?

I have simple array
array(
array( 'id'=>5, 'something' => 2, 'dsadsa' => 'fsfsd )
array( 'id'=>20, 'something' => 2, 'dsadsa' => 'fsfsd )
array( 'id'=>30, 'something' => 2, 'dsadsa' => 'fsfsd )
)
How to create associative array by id field (or something else) from it in the right way?
array(
'5' => array( 'something' => 2, 'dsadsa' => 'fsfsd )
'20' => array( 'something' => 2, 'dsadsa' => 'fsfsd )
'30' => array( 'something' => 2, 'dsadsa' => 'fsfsd )
)
Something along these lines.
$new_array = array();
foreach ($original_array as &$slice)
{
$id = (string) $slice['id'];
unset($slice['id']);
$new_array[$id] = $slice;
}
#NikitaKuhta, nope. There is no slice function which returns a column of values in a 2D keyed table associated with a given key or column heading. You can use some of the callback array_... functions, but you will still need to execute a custom function per element so its just not worth it. I don't like Core Xii's solution as this corrupts the original array as a side effect. I suggest that you don't use references here:
$new_array = array();
foreach ($original_array as $slice) {
$id = (string) $slice['id'];
unset($slice['id']);
$new_array[$id] = $slice;
}
# And now you don't need the missing unset( $slice)

function calling itself

again with another problem.
public function __construct() {
$_GET = $this->clean($_GET);
$_POST = $this->clean($_POST);
...
}
public function clean($data) {
if (is_array($data)) {
foreach ($data as $key => $value) {
unset($data[$key]);
$data[$this->clean($key)] = $this->clean($value);
}
} else {
$data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
}
return $data;
}
i dont understand why $data[$this->clean($key)] = $this->clean($value); is calling its own function. what is the point of doing this? the advantages
thanks,
daniel
It's a technique called recursion. This particular function descends into the structure until it is dealing with very simple data and sanitizes it all.
Given this:
$arr = array (
'<foo' => array(
'bat' => 'OMGWTFBBQ!!><!?!'
),
'bar' => 'baz'
);
It would start:
is arr an array?
is <foo an array? (no)
<foo becomes <foo
<foo used as a key
is the value of <foo an array? (yes)
Is bat an array? (no)
bat remains as is (still has htmlspecialchars called, but it does not change anything))
Is 'OMGWTFBBQ!!><!?!' an array (no)?
'OMGWTFBBQ!!><!?!' is converted to 'OMGWTFBBQ!!><!?!'
'OMGWTFBBQ!!><!?!' is used for the value for bat.
Is 'bar' an array? (no)
bar returned as is (like bat above)
Is baz an array? (no)
baz returned as is.
You can think of it this way
$arr = array (
'<foo' => array(
'bat' => 'OMGWTFBBQ!!><!?!'
),
'bar' => 'baz'
);
///////////////////////////////////////////
array (
clean('<foo') => array(
'bat' => 'OMGWTFBBQ!!><!?!'
),
'bar' => 'baz'
);
///////////////////////////////////////////
array (
'<foo' => clean( array(
'bat' => 'OMGWTFBBQ!!><!?!'
)),
'bar' => 'baz'
);
///////////////////////////////////////////
array (
'<foo' => array(
clean( 'bat' ) => 'OMGWTFBBQ!!><!?!'
)),
'bar' => 'baz'
);
///////////////////////////////////////////
array (
'<foo' => array(
'bat' => clean( 'OMGWTFBBQ!!><!?!' )
)),
'bar' => 'baz'
);
///////////////////////////////////////////
array (
'<foo' => array(
'bat' => 'OMGWTFBBQ!!><!?!'
)),
clean( 'bar' ) => 'baz'
);
///////////////////////////////////////////
array (
'<foo' => array(
'bat' => 'OMGWTFBBQ!!><!?!'
)),
'bar' => clean( 'baz' )
);
///////////////////////////////////////////
return array (
'<foo' => array(
'bat' => 'OMGWTFBBQ!!><!?!'
)),
'bar' => 'baz'
);
clean function uses htmlspecialchars to clean html chars from string. But if $data is an array it calls itself for cleaning all of its keys and values. This is why clean is recursive.
The advantage of this approach is clean function works for string and array transparently.
It's called recursion.
In your example the $_GET and $_POST arrays may contain elements which are also arrays which themselves can contain arrays (ad infinitum). So you don't know how many sub-arrays you will have to clean up.
To solve this problem the function clean is written in a manner that it calls itself when it occurs a "sub array" while cleaning the current array. It's like a loop just for nested data structures.

Sorting an array by a certain key

I have the following array:
Array
(
[Places] => Array
(
[public] => 0
[entities] => Array
(
...
)
)
[Issues] => Array
(
[public] => 1
[entities] => Array
(
...
)
)
[Source] => Array
(
[public] => 0
[entities] => Array
(
...
)
)
)
I would like to be able to sort by the array by the public key. I know I may have to use either ksort or usort but I am unsure on how to implement this.
Any ideas would be great thanks!
usort($array, function ($a, $b) { return $a["public"] - $b["public"]; });
Here's an interesting link: http://www.the-art-of-web.com/php/sortarray/
I would try a
usort(usort(array, function), function);
I can try a sample code upon request, but the information is already there for the taking.
take a look at this, using array_multisort :
$test = array(
'Places' => array(
'public' => 0,
'entities' => array(
)
),
'Issues' => array(
'public' => 1,
'entities' => array()
),
'Source' => array(
'public' => 0,
'entities' => array()
)
);
echo '<pre>';
print_r($test);
echo '</pre>';
array_multisort($test,SORT_ASC,$test);
echo '<pre>';
print_r($test);
echo '</pre>';
The general way to do this using array_multisort is to place your sorting value into its own array and then sort both arrays using that as the primary sorting array.
Try the following:
$test = array(
'Places' => array(
'public' => 0,
'entities' => array(
)
),
'Issues' => array(
'public' => 1,
'entities' => array()
),
'Source' => array(
'public' => 0,
'entities' => array()
)
);
echo '<pre>';
print_r($test);
echo '</pre>';
$sort = array();
foreach ($test as $k => $a) {
$sort[$k] = $a['public'];
}
// placing $sort first in array_multisort causes $test to be sorted in same order as the values in $sort
array_multisort($sort,SORT_ASC,$test);
echo '<pre>';
print_r($test);
echo '</pre>';
You could use usort with callback function.
function cmp($a, $b) {
return $a['public'] == $b['public'] ? 0 : $a['public'] > $b['public'] ? 1 : -1;
}
usort($array, "cmp");
Try this:
$code = "return (-1*strnatcmp(\$a['public'], \$b['public']));";
uasort($array, create_function('$a,$b', $code));

Categories