I have the following array:
$var_array = array(
"length" => 5,
"breadth" => 5,
"color" => "blue",
"size" => "medium",
"shape" => "square");
How do I extract selected variables out of the array by specifying the keys?
Example if I specify breadth and size, I get:
$breadth = 5;
$size = "medium";
$var_array = array(
"length" => 5,
"color" => "blue",
"shape" => "square");
array_diff_key and array_intersect_key:
$array = array(
'breadth' => 1,
'size' => 2,
'length' => 3,
'colour' => 4,
'shape' => 5
);
$keys = array('breadth', 'size');
$new_array = array_intersect_key($array, array_flip($keys));
$array = array_diff_key($array, $new_array);
Will produce:
// $new_array
array(2) {
["breadth"] => int(1)
["size"] => int(2)
}
// $array
array(3) {
["length"] => int(3)
["colour"] => int(4)
["shape"] => int(5)
}
If you want to put them into local variables you can do:
list($length, $colour, $shape) = array_values($new_array);
Or a less clear version:
extract($new_array);
Solution:
$keys = array('breadth', 'size'); // which keys do you want to extract?
foreach($keys as $key) {
$newArr[$key] = $var_array[$key]; // put'em in newArr
unset($var_array[$key]);
}
extract($newArr); // extract them to convert keys to variables
unset($newArr); // unset newArr
goldenparrot has already provided a good answer, but in case you want a solution that doesn't use foreach, you could use array_intersect_key instead:
$var_array = array(...)
$keysToExtract = array('breadth', 'size');
extract(array_intersect_key($var_array, array_fill_keys($keysToExtract, true));
Try this
$var_array = array(
"length" => 5,
"breadth" => 5,
"color" => "blue",
"size" => "medium",
"shape" => "square");
reset($var_array);
$myarray =array();
while (list($key, $val) = each($var_array))
{
if($key!='length' && $key!='size' )
{
$myarray[$key] = $val;
}else{
echo "$key => $val<br />";
}
}
output
size=> medium
breadth => 5
Array
(
[color] => blue
[length] => 5
[shape] => square
)
Related
I have an PHP array :
$datas = array(
"abcd" => array(
"1639340364" => 1,
"1639362752" => 85,
"1639363500" => 74,
),
"efgh" => array(
"1639340364" => 78,
"1639362754" => 98,
"1639363500" => 46,
),
"ijkl" => array(
"1639340364" => 78,
"1639362754" => 98,
"1639363505" => 46,
),
);
I want to check the keys of each array and if not match need to add it on every array.
Expecting output like:
$datas = array(
"abcd" => array(
"1639340364" => 1,
"1639362752" => 85,
"1639362754" => 0,
"1639363500" => 74,
"1639363505" => 0,
),
"efgh" => array(
"1639340364" => 78,
"1639362752" => 0,
"1639362754" => 98,
"1639363500" => 46,
"1639363505" => 0,
),
"ijkl" => array(
"1639340364" => 78,
"1639362752" => 0,
"1639362754" => 98,
"1639363500" => 0,
"1639363505" => 46,
),
);
If the key is not exist need to add the key with value zero. Is that possible?
I tried with array_key_exists() function...
But I'm not sure where I want to check, when I'm checking It's return true(1). I know it's checking on the same array, Actually I want to know where I will check the condition?
foreach($datas as $key => $data ){
print_r($data);
foreach($data as $key => $point ){
$val = array_key_exists($key,$data);
echo $val;
}
}
I came up with this:
// prepare default keys
$keys = [];
foreach ($datas as $data) {
$keys = array_merge($keys, array_keys($data));
}
$keys = array_unique($keys);
sort($keys);
// construct default array with zeros
$default = array_combine($keys, array_fill(0, count($keys), 0));
// insert the default array
foreach ($datas as $key => $data) {
$datas[$key] = array_replace($default, $data);
}
// show result
echo '<pre>';
print_r($datas);
echo '</pre>';
I needed used a plethora of array functions. The idea is this: First I gather all the possible 'keys' from the array, make them unique, sort them and combine them into a new 'default' array containing only zero values. After that I use the array_replace() function to insert this array into the existing $datas array. This function does exactly what you want:
array_replace() replaces the values of array with values having the
same keys in each of the following arrays. If a key from the first
array exists in the second array, its value will be replaced by the
value from the second array.
It's not pretty or optimised, but here you go:
$subkeys = array();
foreach ($datas as $k => $d) {
foreach($d as $k2 => $d2) {
$subkeys[$k2] = 0;
}
}
foreach ($datas as $k => &$d) {
foreach ($subkeys as $xk => $xd) {
if ( ! array_key_exists($xk, $d)) {
$d[$xk] = $xd;
}
}
}
Is there built-in function, or shorter way to extract elements into new array, as described here?
<?php
function arr_slice ($arr, $keys) {
$ret = array();
foreach ($keys as $k) { $ret[$k] = $arr[$k]; }
return $ret;
}
$array = array(
"a" => 1,
"b" => 2,
"c" => 3,
"d" => 4,
);
var_export(
arr_slice($array, array("x","d","b"))
);
output (key order matters)
array (
'x' => NULL,
'd' => 4,
'b' => 2,
)
I have the following array:
array(10) {
[0]=> array(109) {
["id"]=> string(4) "2632", ["_category_sortorder"] => 8, ["_sortorder" => 1]
},
[1]=> array(109) {
["id"]=> string(4) "2635", ["_category_sortorder"] => 5, ["_sortorder" => 2]
},
...
}
I want to sort it based on two criterias:
a) by _category_sortorder asc (with priority)
b) by _sortorder asc
I tried this:
foreach($resources as $k => $v) {
$sort[$k]['_category_sortorder'] = $resources[$k]['_category_sortorder'];
$sort[$k]['_sortorder'] = $resources[$k]['_sortorder'];
}
array_multisort($sort['_category_sortorder'], SORT_ASC, $sort['_sortorder'], SORT_ASC, $resources);
But it's not working as expected. Any suggestions?
Try like this,
$sort = array(
array("id"=>"263", "_category_sortorder"=> 8, "_sortorder" => 1),
array( "id"=> "145", "_category_sortorder" => 155, "_sortorder" => 2),
array( "id"=> "2145", "_category_sortorder" => 55, "_sortorder" => 12),
array( "id"=> "3145", "_category_sortorder" => 155, "_sortorder" => 10),
);
usort($sort, function(array $a, array $b) {
return $b['_category_sortorder'] - $a['_category_sortorder'];
});
echo '<pre>';
print_r($sort);
echo '</pre>';
I think there is a simple solution but this code block is doing is job:
You split the array in sub arrays including only elements with the same _category_sortorder value. Then you sort each sub array with usort. At the end you merge them together.
<?php
$array = [
['id' => 1, '_category_sortorder' => 2, '_sortorder' => 1],
['id' => 2, '_category_sortorder' => 2, '_sortorder' => 3],
['id' => 3, '_category_sortorder' => 3, '_sortorder' => 19],
['id' => 4, '_category_sortorder' => 1, '_sortorder' => 2],
['id' => 5, '_category_sortorder' => 1, '_sortorder' => 1],
];
foreach ($array as $value) {
if (!isset($newElements[$value['_category_sortorder']]))
$newElements[$value['_category_sortorder']] = [];
$newElements[$value['_category_sortorder']][] = $value;
}
$array = [];
foreach ($newElements as $key => $value) {
usort($value, function($a, $b) {
return strcmp($a["_sortorder"], $b["_sortorder"]);
});
$array[$key] = $value;
}
ksort($array);
$new = [];
foreach ($array as $value) {
$new = array_merge($new, $value);
}
echo "<pre>".print_r($new, true).'</pre>';
I use this code :
$new = array(
"123" => "a",
"456" => "b"
);
$old = array(
"123" => "a",
"456" => "b"
);
then the $new array become like this:
$new = array(
"456" => "b",
"123" => "c",
"789" => "e"
);
as you see the count of $new array increased and the order of elements changed and the value at key 123 also changed. I need to compare the $new array against the $old array and catch only the change made on the value at key 123 without caring about the order and the count of elements. I tried:
$result = array_diff( $new, $old );
print_r( $result );
output :
Array ( [123] => c [789] => e )
UPDATE. quite confusing. now I think we got it
$old = array(
"123" => "a",
"456" => "b"
);
$new = array(
"456" => "b",
"123" => "c", // catch this (element in old array that is changed)
"789" => "e"
);
$new2 = array();
foreach ($new as $key => $new_val)
{
if (isset($old[$key])) // belongs to old array?
{
if ($old[$key] != $new_val) // has changed?
$new2[$key] = $new[$key]; // catch it
}
}
// output $new2:
array (
123 => 'c',
)
You first of all want to have those elements of $new that are changed compared to $old (see array_diff_assoc):
$changed = array_diff_assoc($new, $old);
Of that result you want to have only those elements that have their key in $old (see array_intersect_key):
$result = array_intersect_key($changed, $old);
And that's it. You can wrap that into each other if it helps:
array_intersect_key(array_diff_assoc($new, $old), $old);
Result is:
array(1) {
[123] =>
string(1) "c"
}
Full example (Demo):
$old = array(
"123" => "a",
"456" => "b"
);
$new = array(
"456" => "b",
"123" => "c", // catch only the change made on the value at key 123
"789" => "e"
);
$changed = array_diff_assoc($new, $old);
$result = array_intersect_key($changed, $old);
var_dump($result);
Just a final note: There are many array functions in PHP. It's worth to go through the list and look what is fitting because most often you only need one or two of them to get things like these done.
You use this code for your requirements
<?php
function key_compare_func($key1, $key2)
{
if ($key1 == $key2)
return 0;
else if ($key1 > $key2)
return 1;
else
return -1;
}
$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
var_dump(array_intersect_ukey($array1, $array2, 'key_compare_func'));
?>
$arr = array(
'a1'=>'1',
'a2'=>'2'
);
I need to move the a2 to the top, as well as keep the a2 as a key how would I go on about it I can't seem to think a way without messing something up :)
Here is a solution which works correctly both with numeric and string keys:
function move_to_top(&$array, $key) {
$temp = array($key => $array[$key]);
unset($array[$key]);
$array = $temp + $array;
}
It works because arrays in PHP are ordered maps.
Btw, to move an item to bottom use:
function move_to_bottom(&$array, $key) {
$value = $array[$key];
unset($array[$key]);
$array[$key] = $value;
}
You can achieve that this way:
$arr = array(
'a1'=>'1',
'a2'=>'2'
);
end($arr);
$last_key = key($arr);
$last_value = array_pop($arr);
$arr = array_merge(array($last_key => $last_value), $arr);
/*
print_r($arr);
will output (this is tested):
Array ( [a2] => 2 [a1] => 1 )
*/
try this:
$key = 'a3';
$arr = [
'a1' => '1',
'a2' => '2',
'a3' => '3',
'a4' => '4',
'a5' => '5',
'a6' => '6'
];
if (isset($arr[ $key ]))
$arr = [ $key => $arr[ $key ] ] + $arr;
result:
array(
'a3' => '3',
'a1' => '1',
'a2' => '2',
'a4' => '4',
'a5' => '5',
'a6' => '6'
)
Here's a simple one liner to get this done with array_splice() and the union operator:
$arr = array('a1'=>'1', 'a2'=>'2', 'a3' => '3');
$arr = array_splice($arr,array_search('a2',array_keys($arr)),1) + $arr;
Edit:
In retrospect I'm not sure why I wouldn't just do this:
$arr = array('a2' => $arr['a2']) + $arr;
Cleaner, easier and probably faster.
You can also look at array_multisort This lets you use one array to sort another. This could, for example, allow you to externalize a hard-coded ordering of values into a config file.
<?php
$ar1 = array(10, 100, 100, 0);
$ar2 = array(1, 3, 2, 4);
array_multisort($ar1, $ar2);
var_dump($ar1);
var_dump($ar2);
?>
In this example, after sorting, the first array will contain 0, 10, 100, 100. The second array will contain 4, 1, 2, 3. The entries in the second array corresponding to the identical entries in the first array (100 and 100) were sorted as well.
Outputs:
array(4) {
[0]=> int(0)
[1]=> int(10)
[2]=> int(100)
[3]=> int(100)
}
array(4) {
[0]=> int(4)
[1]=> int(1)
[2]=> int(2)
[3]=> int(3)
}