unset array keys if key is string - php

i have array something like this
$arr =
['0' =>
['0' => 'zero',
'1' => 'test',
'2' =>'testphp',
'test'=>'zero',
'test1'=>'test',
'test2'=>'testphp'],
'1' =>
['0' => 'z',
'1' => 'x',
'2' =>'c',
'test'=>'z',
'test1'=>'x',
'test2'=>'c']
];
and 0,1,2 is this same as test,test1,test2. I need remove keys where is string like test,test1,test2.
I know the way
foreach($arr as $a){
unset($arr['test']);
unset($arr['test1']);
unset($arr['test2']);
}
but it is possible find keys without specifying the exact name, because i want only number keys.

A solution would be:
Assuming you know it will only have 2 layers.
$arr =
['0' =>
['0' => 'zero',
'1' => 'test',
'2' =>'testphp',
'test'=>'zero',
'test1'=>'test',
'test2'=>'testphp'],
'1' =>
['0' => 'z',
'1' => 'x',
'2' =>'c',
'test'=>'z',
'test1'=>'x',
'test2'=>'c']
];
foreach($arr as $parentKey=>$arrayItem){
foreach($arrayItem as $key=>$subArrayItem){
if(!is_int($key)){
unset($arr[$parentKey][$key]);
}
}
}
var_dump($arr);
Why is it though that such arrays have been generated?

edit: after reading Valdorous answer realized it is multidimensional array. the following should handle recursively a multi-dimensional array.
call the function (see below)
remove_non_numeric_keys($arr)
function remove_non_numeric_keys($arr)
{
foreach($arr as $key=>$val)
{
if(!is_numeric($key)) // if not numeric unset it regardless if it is an array or not
{
unset($arr[$key]);
}else{
if(is_array($val) // if it is an array recursively call the function to check the values in it
{
remove_non_numeric_keys($val);
}
}
}
}
This should remove only non-numeric keys.
http://php.net/manual/en/function.is-numeric.php
Hope it helps

Related

Alter array rows to be associative and append an additional associative element

I've created a method that allows me to assign keys to rows of values, and appends extra keys and values.
It adds all the new keys to a keys array, then adds all new values to the values array, and then combines all the keys and values.
How can I shrink it to make it smaller and more efficient?
$valores = array(array("1","1","1","1"),array("2","2","2","2"));//array of values
$keys = array('k1','k2','k3','k4'); //array of keys
$id = array('SpecialKey' => 'SpecialValue');//new array of items I want to add
function formatarArray($arrValores,$arrKeys,$identificadores){
foreach($identificadores as $k => $v){
array_push($arrKeys, $k);
}
foreach($arrValores as $i => $arrValor)
{
foreach($identificadores as $k => $v){
array_push($arrValor, $v);
}
$arrValores[$i] = array_combine($arrKeys, $arrValor);
}
var_export($arrValores);
}
Output:
array (
0 =>
array (
'k1' => '1',
'k2' => '1',
'k3' => '1',
'k4' => '1',
'SpecialKey' => 'SpecialValue',
),
1 =>
array (
'k1' => '2',
'k2' => '2',
'k3' => '2',
'k4' => '2',
'SpecialKey' => 'SpecialValue',
),
)
Viper-7(code debug):
http://viper-7.com/hbE1YF
function formatarArray($arrValores, $arrKeys, $identificadores)
{
foreach ($arrValores as &$arr)
$arr = array_merge(array_combine($arrKeys, $arr), $identificadores);
print_r($arrValores);
}
Could even be done in one line...
function formatarArray($arrValores, $arrKeys, $identificadores)
{
print_r(array_map(function ($arr) use ($arrKeys, $identificadores) { return array_merge(array_combine($arrKeys, $arr), $identificadores); }, $arrValores));
}
As a modernized form of #havenard's answer, I'd use PHP7.4's arrow function syntax to avoid the need for use() and I would use the array union operator (+) to avoid the iterated array_merge() calls. The array union operator is appropriate because it is adding an associative array to another array.
Code: (Demo)
var_export(
array_map(
fn($row) => array_combine($keys, $row) + $id,
$valores
)
);

Array combined with another array - how to do this elegantly

I've got two arrays, an array of integers and an array of strings. I want to combine these two, but this is proving troublesome to me.
Basically, the first value in each array will be associated, the second value of each array will be associated, third with each other, and so on.
I've got a foreach loop iterating over and using $result as array key, as such:
foreach ($results as $result) {
And then a function to generate $order based on said string.
I am then trying to associate each value as I said, where I would have something like:
array('8' => 'value', '8' => 'value', '6' => 'anothervalue', '6' => 'anothervalue');
Here's the code I have.
$order = resource_library_apachesolr_resource_type_order($resource_type);
$result['resource_type'] = $resource_type;
$newresults = array($order => $result);
$order isn't iterating, so how would I make it so that I get the iterated value of $order combined with the currently iterating value of $result?
Well, since you have repeated keys, you can't use array_combine
You might have to get a bit creative. Maybe casting to string and adding 0 before the integer part...
EXAMPLE:
$a1 = array(1,1,2,3,3);
$a2 = array('a', 'b', 'c', 'd', 'e');
$a3 = array();
for ($i=0; $i<count($a1); ++$i) {
$key = (string) $a1[$i];
$val = (String) $a2[$i];
while (isset($a3[$key])) {
$key = "0$key";
}
$a3[$key] = $val;
}
var_dump($a3);
foreach ($a3 as $key => $val) {
$key = (int) $key;
print "$key=>$val<br>";
}
OUTPUTS:
array (size=5)
1 => string 'a' (length=1)
'01' => string 'b' (length=1)
2 => string 'c' (length=1)
3 => string 'd' (length=1)
'03' => string 'e' (length=1)
1=>a
1=>b
2=>c
3=>d
3=>e
I don't know why you need this, but if I want to do something like that I'll do:
$arr = array();
foreach($numbers as $i=>$num){
$arr[$num][] = $strings[$i];
}
and will get:
array(
1 => array(
a,
b
),
2 => array(
c
),
3 => array(
d,
e
)
)

Merge possible values to array when comparing two arrays

I'm looking for a simple solution to merge two arrays. They both look mostly alike, except one key-value-pair. I want my result to have an array with both possible values.
The xdebugged arrays look like this (simplified):
array (size=3)
'entry' => string '18' (length=2)
'mykey' => string 'value1' (length=6) // here is the difference
'something' => string '1' (length=1)
array (size=3)
'entry' => string '18' (length=2)
'mykey' => string 'value2' (length=6)) // here is the difference
'something' => string '1' (length=1)
I'd like the result to be:
array (size=2)
'entry' => string '18' (length=2)
'mykey' => array (size=2)) // both values merged to array
'0' => 'value1' (length=6)
'1' => 'value2' (length=6)
'something' => string '1' (length=1)
How to achieve this easily?
Would this suffice:
<?php
$array1 = array(
'entry'=>'18',
'mykey'=>'value1',
'something'=>'1'
);
$array2 = array(
'entry'=>'18',
'mykey'=>'value2',
'something'=>'1'
);
$output = array();
foreach($array1 as $k=>$v){
if(isset($array2[$k]) && $array2[$k] === $v){
$output[$k] = $v;
}elseif(isset($array2[$k])){
$output[$k][] = array($v,$array2[$k]);
}else{
$output[$k] = $v;
}
}
foreach($array2 as $k=>$v){
if(!array_key_exists($k,$output)){
$output[$k] = $v;
}
}
echo '<pre>',print_r($output),'</pre>';
Edit:I do like the use of array_merge_recursive() mentioned by Ziarno, but the issue is that it will create an array for each key. So I have added the use of array_unique(), then checking if the length is 1, and flattening it if so.
$output = array_merge_recursive($array1, $array2);
foreach($output as $k=>&$v){
$v = array_unique($v);
if(count($v)==1){
$v = $v[0];
}
}
echo '<pre>',print_r($output),'</pre>';
You need to write your own custom code for this.
// Get all the key values.
foreach($arrays as $array){
$keys[] = $array['mykey']
}
// retain 1st element & discard others.
$array = array_slice($arrays, 0, 1);
// update to the 1st array element
$array['mykey'] = $keys;
// print
print_r($array);
Hope this will help.
I think this function is designed exactly for what you need:
array_merge_recursive($array1, $array2)

How can I efficiently split an array into its associative key arrays?

How can I split a single array into it's sub-keys?
$arr = array(
0 => array(
'foo' => '1',
'bar' => 'A'
),
1 => array(
'foo' => '2',
'bar' => 'B'
),
2 => array(
'foo' => '3',
'bar' => 'C'
)
);
What is the most efficient way to return an array of foo and bar separately?
I need to get here:
$foo = array('1','2','3');
$bar = array('A','B','C');
I'm hoping there's a clever way to do this using array_map or something similar. Any ideas?
Or do I have to loop through and build each array that way? Something like:
foreach ($arr as $v) {
$foo[] = $v['foo'];
$bar[] = $v['bar'];
}
In a lucky coincidence, I needed to do almost the exact same thing earlier today. You can use array_map() in combination with array_shift():
$foo = array_map('array_shift', &$arr);
$bar = array_map('array_shift', &$arr);
Note that $arr is passed by reference! If you don't do that, then each time it would return the contents of $arr[<index>]['foo']. However, again because of the reference - you won't be able to reuse $arr, so if you need to do that - copy it first.
The downside is that your array keys need to be ordered in the same way as in your example, because array_shift() doesn't actually know what the key is. It will NOT work on the following array:
$arr = array(
0 => array(
'foo' => '1',
'bar' => 'A'
),
1 => array(
'bar' => 'B',
'foo' => '2'
),
2 => array(
'foo' => '3',
'bar' => 'C'
)
);
Update:
After reading the comments, it became evident that my solution triggers E_DEPRECATED warnings for call-time-pass-by-reference. Here's the suggested (and accepted as an answer) alternative by #Baba, which takes advantage of the two needed keys being the first and last elements of the second-dimension arrays:
$foo = array_map('array_shift', $arr);
$bar = array_map('array_pop', $arr);
$n = array();
foreach($arr as $key=>$val) {
foreach($val as $k=>$v) {
$n[$k][] = $v;
}
}
array_merge_recursive will combine scalar values with the same key into an array. e.g.:
array_merge_recursive(array('a',1), array('b',2)) === array(array('a','b'),array(1,2));
You can use this property to simply apply array_merge_recursive over each array in your array as a separate argument:
call_user_func_array('array_merge_recursive', $arr);
You will get this result:
array (
'foo' =>
array (
0 => '1',
1 => '2',
2 => '3',
),
'bar' =>
array (
0 => 'A',
1 => 'B',
2 => 'C',
),
)
It won't even be confused by keys in different order.
However, every merged value must be scalar! Arrays will be merged instead of added as a sub-array:
array_merge_recursive(array(1), array(array(2)) === array(array(1,2))
It does not produce array(array(1, array(2)))!

How do I sort a multi-dimensional array by value?

I have an array as following and I want to order that array by the value of the key "attack". First keys of the arrays (15, 13, 18) are ID of some certain item from database, so I don't want these keys to be changed when the array is sorted. Any help would be greatly appreciated.
This is the array:
$data = array(
'15' => array(
'attack' => '45', 'defence' => '15', 'total' => '10'
),
'13' => array(
'attack' => '25', 'defence' => '15', 'total' => '10'
),
'18' => array(
'attack' => '35', 'defence' => '15', 'total' => '10'
)
);
Use uasort():
This function sorts an array such that array indices maintain their correlation with the array elements they are associated with, using a user-defined comparison function.
This is used mainly when sorting associative arrays where the actual element order is significant.
Example:
function cmp($a, $b) {
if ($a['attack'] == $b['attack']) {
return 0;
}
return ($a['attack'] < $b['attack']) ? -1 : 1;
}
uasort($data, 'cmp');
If the values are always strings, you can also use strcmp() in the cmp() function:
function cmp($a, $b) {
return strcmp($a['attack'], $b['attack']);
}
Update:
To sort in descending order you just have to change the return values:
return ($a['attack'] < $b['attack']) ? 1 : -1;
// ^----^
or to pick up #salathe's proposal:
return $b['attack'] - $a['attack'];
Simply use array_multisort
foreach ($data as $key => $row) {
$attack[$key] = $row['attack'];
}
// Sort the data with attack descending
array_multisort($attack, SORT_DESC, $data);
Hope this helps.
$result = [];
foreach ($data as $key => $value) {
$result[$key] = $value;
asort($result[$key]);
}
print_r($result);
Hope this helps !!!

Categories