I have an interesting task which can not handle. I have an PHP array that is generated automatically and randomly once a multi-dimensional, associative or mixed.
$data['sport']['basketball']['team']['player']['position']['hand']['name']['finalelement']
$data['sport']['basketball']['team']['player'][0]['position']['hand']['name']['finalelement']
$data['sport']['basketball']['team']['player'][0]['position']['hand']['name'][0]['finalelement']
$data['sport']['basketball']['team']['player']['position']['hand']['name'][0]['finalelement']
The goal is, no matter whether it is multidimensional or associative get to the final element. There is a simple way that has few if conditions. But I want to ask if you have an idea if there is any more intreresen way?
you may use array_walk_recursive as follows :
$data['sport']['basketball']['team']['player']['position']['hand']['name']['finalelement'] = 'e1';
$data['sport']['basketball']['team']['player'][0]['position']['hand']['name']['finalelement'] = 'e2';
$data['sport']['basketball']['team']['player'][0]['position']['hand']['name'][0]['finalelement'] = 'e3';
$data['sport']['basketball']['team']['player']['position']['hand']['name'][0]['finalelement'] = 'e4';
$list = [];
array_walk_recursive($data, function ($value, $key) use (&$list) {
$list[] = $value;
});
print_r($list);
This will Output the following:
Array (
[0] => e1
[1] => e4
[2] => e2
[3] => e3
)
Next code returns first deepest value that is not an array:
$data['sport']['basketball']['team']['player']['position']['hand']['name'][0]['finalelement'] = 'end';
$current = $data;
while (is_array($current)) {
$current = array_values($current)[0];
}
print $current; // end
Related
I have a 2D array like
attendee_programs = [1 =>[100,101],
2 =>[100,101,102]
];
I want to get array_values() and array_unique() but only for the nested elements (sorry, not sure what the terminology is) ...I.E.
programs = [100,101,102];
Is there a php function for this? or do I need to loop through and assemble it manually?
Edit: All of the answers are very helpful and have shown me something new. Sorry I can only accept one.
You could use a clever combination of array_unique, array_reduce and array_merge to achieve this:
$a = array_unique(array_reduce($attendee_programs, 'array_merge', []));
Doing this might be end in an array with some gaps in the indizes - if you need gaples array keys, you have to add array_values at the end
$a = array_values($a);
You can use:
call_user_func_array('array_merge', array_values($attendee_programs));
to get values of nested array.
array_unique(call_user_func_array('array_merge', array_values($attendee_programs)));
to get unique values.
RecursiveIteratorIterator
RecursiveArrayIterator
Solution:
function flatten($array)
{
$rit = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
return iterator_to_array($rit, true);
}
echo '<pre>';
print_r(flatten($attendee_programs));
Result:
Array
(
[0] => 100
[1] => 101
[2] => 102
)
Yet another option:
$flat = array();
array_walk_recursive($attendee_programs, function($value) use (&$flat) {
$flat[] = $value;
});
$flat = array_unique($flat);
I have two arrays
Array 1:
$strong_areas=array(
'192'=>57,
'187'=>43,
'121'=>85,
'198'=>74
);
Array 2:
$weak_areas=array(
'109'=>57,
'187'=>54,
'181'=>85,
'198'=>25
);
I need resultant array like this:
array(
'192'=>57, //57-0
'187'=>-11, //43-54
'121'=>85, //85-0
'198'=>49, //74-25
'109'=>-57, // 0-57
'181'=>-85, //0-85
)
What I tried so far:
//for common keys in both arrays
$temp=array_intersect_key($strong_areas,$weak_areas);
//for unique ones from first to second
$strong_final_array=array_diff_key($strong_areas, $weak_areas);
//for unique ones from second to first
$weak_final_array=array_diff_key($weak_areas, $strong_areas);
foreach ($weak_final_array as &$value){
$value *= (-1);
}
//returning final values for common keys in array
$common=array();
foreach($temp as $key => $value){
$common[$key]=$strong_areas[$key]-$weak_areas[$key];
}
//getting final results
$final_array=array_merge($strong_final_array,$weak_final_array,$common);
The question is, is the above procedure best practice or is there any easier way to do this?
You can use like this
$final_result = array();
foreach (array_keys($strong_areas + $weak_areas) as $join_key) {
$final_result[$join_key] = ( isset($strong_areas[$join_key]) ? $strong_areas[$join_key] : 0 ) - ( isset($weak_areas[$join_key]) ? $weak_areas[$join_key] : 0 );
}
print_r($final_result);
The output array is
Array
(
[192] => 57
[187] => -11
[121] => 85
[198] => 49
[109] => -57
[181] => -85
)
You should use native php function: array_merge_recursive and array_walk. The benefit is they're php core function (which is written in C) and execute faster than using php foreach.
// this will return array with keys combined from argument arrays,
// value will be scalar if key only exist in 1 argument,
// and value will be array if key exist in multiple arguments
$result_array = array_merge_recursive($strong_areas,$weak_areas);
// this step will walk through result array and change its array value
// into subtraction of elements
array_walk($result_array, function ($element) {
if (is_array($element)) {
return $element[0] - $element[1];
} else {
return $element;
}
});
It's just sample code. You can make it more fancy by yourself
Regards,
I am trying to make a function where I get data from specific positions in an array, and then add(plus) the results together. Something like this:
$specificPositionsInArray = "1,4,12,27,40,42,48,49,52,53,56,58";
$dataArray = "1,2,3,4,5,6,7,8"; // More than hundred values.
myfunction($specificPositionsInArray) {
// Find position in array, based on $specificPositionsInArray and then
// plus the value with the previous value
// that is found in the $specificPositionsInArray.
// Something like:
$value = $value + $newValue;
return $value;
}
So if $specificPositionsInArray was 1,3,5
The $value that should be returned would be: 9 (1+3+5) (based on the $dataArray).
Maybe there is another way to do it, like without the function.
Here's a functional approach:
$specificPositionsInArray = array(1,3,7,6);
$dataArray = array(1,2,3,4,5,6,7,8);
function totalFromArrays($specificPositionsInArray, $dataArray) {
foreach ($specificPositionsInArray as $s){
$total += $dataArray[$s];
}
return $total;
}
$total = totalFromArrays($specificPositionsInArray, $dataArray);
echo $total;
You should look into arrays and how to handle them, you could have found the solution pretty easily. http://www.php.net/manual/en/book.array.php
//$specificPositionsInArray = array(1,4,12,27,40,42,48,49,52,53,56,58);
$specificPositionsInArray = array(1,3,5);
$dataArray = array(1,2,3,4,5,6,7,8);
$total=0;
foreach($specificPositionsInArray as $k => $v){
$total += $dataArray[$v-1];
}
echo $total;
The weird part about this is the $v-1 but because of how you want to handle the addition of the items, and an array starts with element 0, you have to subtract 1 to get to the right value.
So you want to do something like this:
$dataArray = array(1,2,3,4,5...); // 100+ values, not necessarily all integers or in ascending order
$specificPositions = array(1, 3, 5);
function addSpecificPositions($data, $positions) {
$sum = 0;
foreach($positions as $p)
$sum += $data[$p];
return $sum;
}
If you really want to keep your list of values in a string (like you have it in your example), you'll have to do an explode first to get them in array form.
Since it looks like your array is using numeric values for the keys this should be fairly easy to calculate. I refactored your code a little to make it easier to read:
$specificPositionsInArray = array(1,4,6,7);
By default PHP will assign numeric keys to each value in your array, so it will look like this to the interpreter.
array(
[0] => 1,
[1] => 4,
[2] => 6,
[3] => 7
)
This is the same for all arrays unless you specify a numeric or mixed key. Since the data array seems to just be values, too, and no keys are specified, you can simply target them with the key that they will be associated with. Say I use your array example:
$dataArray = array(1,2,3,4,5,6,7,8);
This will look like this to the parser:
array(
[0] => 1,
[1] => 2,
[2] => 3,
[3] => 4,
[4] => 5,
[5] => 6,
[6] => 7,
[7] => 8
)
If you wanted to select the number 6 from this array, you actually need to use $dataArray[5] since array keys start at zero. So for your function you would do this:
$specificPositionsInArray = array(1,4,6,7);
$dataArray = array(1,2,3,4,5,6,7,8);
calculate_array($specificPositionsInArray, $dataArray); // Returns 18
function calculate_array($keys, $data){
$final_value = 0; // Set final value to 0 to start
// Loop through values
foreach($keys as $key){
// Add the keys to our starting value
$final_value += $data[$key-1]; // minus 1 from key so that key position is human readable
}
// return the sum of the values
return $final_value;
}
This question already has answers here:
php - how to remove all elements of an array after one specified
(3 answers)
Closed 9 years ago.
Is it possible to delete all array elements after an index?
$myArrayInit = array(1=>red, 30=>orange, 25=>velvet, 45=>pink);
now some "magic"
$myArray = delIndex(30, $myArrayInit);
to get
$myArray = array(1=>red, 30=>orange);
due to the keys in $myArray are not successive, I don't see a chance for array_slice()
Please note : Keys have to be preserved! + I do only know the Offset Key!!
Without making use of loops.
<?php
$myArrayInit = [1 => 'red', 30 => 'orange', 25 => 'velvet', 45 => 'pink']; //<-- Your actual array
$offsetKey = 25; //<--- The offset you need to grab
//Lets do the code....
$n = array_keys($myArrayInit); //<---- Grab all the keys of your actual array and put in another array
$count = array_search($offsetKey, $n); //<--- Returns the position of the offset from this array using search
$new_arr = array_slice($myArrayInit, 0, $count + 1, true);//<--- Slice it with the 0 index as start and position+1 as the length parameter.
print_r($new_arr);
Output :
Array
(
[1] => red
[30] => orange
[25] => velvet
)
Try
$arr = array(1=>red, 30=>orange, 25=>velvet, 45=>pink);
$pos = array_search('30', array_keys($arr));
$arr= array_slice($arr,0,$pos+1,true);
echo "<pre>";
print_r($arr);
See demo
I'd iterate over the array up until you reach the key you want to truncate the array thereafter, and add those items to a new - temporary array, then set the existing array to null, then assign the temp array to the existing array.
This uses a flag value to determine your limit:
$myArrayInit = array(1=>'red', 30=>'orange', 25=>'velvet', 45=>'pink');
$new_array = delIndex(30,$myArrayInit);
function delIndex($limit,$array){
$limit_reached=false;
foreach($array as $ind=>$val){
if($limit_reached==true){
unset($array[$ind]);
}
if($ind==$limit){
$limit_reached=true;
}
}
return $array;
}
print_r($new_array);
Try this:
function delIndex($afterIndex, $array){
$flag = false;
foreach($array as $key=>$val){
if($flag == true)
unset($array[$key]);
if($key == $afterIndex)
$flag = true;
}
return $array;
}
This code is not tested
I have 2 arrays with for example 1000 key's each, one holds a temperature value and the other the hour.
Example array temp:
[0] = 3.1
[1] = 4.3
[2] = 4.1
[3] = 5.1
[4] = 4.1
Example hour array:
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = 3
The problem with this is that when i combine these to arrays and plot this in for example pchart i have too many values on the X and it gets cluttered.
So what i need to to remove the duplicate hours and replace then with "NULL", so that the unneeded hours are not plotted on the x axis.
I want to keep the first hour in the array, the second to the end of the duplicates can be set to "NULL"
The hour output array should be:
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = NULL
etc.
Sounds like a job for array_unique().
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
Takes an input array and returns a new array without duplicate values.
Note that keys are preserved. array_unique() sorts the values treated
as string at first, then will keep the first key encountered for every
value, and ignore all following keys. It does not mean that the key of
the first related value from the unsorted array will be kept.
Note: Two elements are considered equal if and only if (string) $elem1
=== (string) $elem2. In words: when the string representation is the same. The first element will be used.
If you require the array keys to persist, you can try something with array_map().
<?php
//Variable initialization
$array = array(
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 3
);
$temp = array();
$array = array_map(function($element) use (&$temp) {
if (!in_array($element, $temp)) {
$temp[] = $element;
return $element;
}
return null;
}, $array);
print_r($array);
Your array is sorted, so... how about this?
$hours = array(0,1,2,3,3,4,4,5);
$prev = -1;
foreach ($hours as &$hour) {
if ($prev === $hour) {
$hour = NULL;
}
else {
$prev = $hour;
}
}
unset($hour);
print_r($hours); // 0,1,2,3,NULL,4,NULL,5...
If you're using php 5.3:
$a = array(0,1,2,3,4,4,5);
array_walk($a, function(&$item) {
static $encountered = array();
if(in_array($item, $encountered)) {
$item = null;
return;
}
$encountered[] = $item;
});
var_dump($a);
Will preserve the number of keys. Array_walk calls a user function for every key. static makes it so that the $encountered array in the scope of the function stays between executions.
If you want to remove the duplicates entirely you can use array_unique()
but it wont set them to NULL.
Maybe this trick does it:
$simplified = array_combine($hours, $temperatures);
$hours = array_keys($simplified);
$temperatures = array_values($simplified);
This won't set things to NULL but to completely remove them which I think is what you're looking for. Otherwise this should do it:
foreach(array_slice(array_reverse(array_keys($hours)), 0, -1) as $i)
($hours[$i] === $hours[$i-1]) && $hours[$i] = NULL;
Demo