Selecting value from array with a range? - php

I've an array on php that will return a lot of keys->values, like this:
Array
[0] => Array
(
[value] => 405
[information] => some information1
)
[1] => Array
(
[value] => 500
[information] => some information2
)
[2] => Array
(
[value] => 700
[information] => some information3
)
the values are numbers, i need to collect all the values, check the first one that will be >= $determinedvalue and then return the value "information" for this exactly array, is this even possible? I know i can do this if i create a temp table on my database, but i dont want to.
To be more clearly, when my value is "430" it will return me "some information2".
I've searched a lot on google but by now i dont know if this is even possible.
Appreciate any help.

This is a sample on how to do that. Comments in code can be used to explain the execution.
// Sample Array
$arr = array(
array
(
"value" => 405,
"information" => "some information1"
),
array
(
"value" => 500,
"information" => "some information2"
),
array
(
"value" => 700,
"information" => "some information3"
)
);
// Sample Number
$numberToCheck = 430;
// Sub Array To Assign
$subArray = array();
// Loop Through Outer Array
for ( $i = 0; $i < sizeof($arr); $i++)
{
// If Value In Array > Number Check
if ( $arr[$i]['value'] >= $numberToCheck )
{
$subArray = $arr[$i]; // Assign Sub Array
$i = sizeof($arr); // This is Used to Exit For Loop
}
}
print_r($subArray); // Print

Working runnable code: https://tech.io/snippet/QJ93AwV
Code snippent with comments:
<?php
/**
* Helper class for stable sort alogithms
* #see https://github.com/vanderlee/PHP-stable-sort-functions
* Class StableSort
*/
class StableSort
{
static public function usort(array &$array, $value_compare_func)
{
$index = 0;
foreach ($array as &$item) {
$item = array($index++, $item);
}
$result = usort($array, function ($a, $b) use ($value_compare_func) {
$result = call_user_func($value_compare_func, $a[1], $b[1]);
return $result == 0 ? $a[0] - $b[0] : $result;
});
foreach ($array as &$item) {
$item = $item[1];
}
return $result;
}
}
$array = [
// added for test sorting
[
'value' => 9999,
'information' => 'some information-1',
],
[
'value' => 1200,
'information' => 'some information0',
],
// \added for test sorting
[
'value' => 405,
'information' => 'some information1',
],
// added for test sorting stability
[
'value' => 405,
'information' => 'some information1.2',
],
[
'value' => 405,
'information' => 'some information1.1',
],
// \added for test sorting stability
[
'value' => 500,
'information' => 'some information2',
],
[
'value' => 700,
'information' => 'some information3',
],
];
// sort array
$determinedvalue = 430;
StableSort::usort($array, function ($item1, $item2) {
if ($item1['value'] == $item2['value']) return 0;
return $item1['value'] < $item2['value'] ? -1 : 1;
});
// then select the first element by condition
$res = null;
foreach($array as $v) {
if($v['value'] >= $determinedvalue) {
$res = $v['information'];
break;
}
}
// for testing
print $res;

$number = 430;
$array = Array
[0] => Array
(
[value] => 405
[information] => some information1
)
[1] => Array
(
[value] => 500
[information] => some information2
)
[2] => Array
(
[value] => 700
[information] => some information3
)
$firstArray = $array[0];
$secondArray = $array[1];
$threeArray = $array[2];
function selectValueFromArrayRange ($number, $start, $end, $value, $infomation)
{
$startValue = $start[$value];
$endValue = $end[$value];
if ( in_array($number, range($startValue, $endValue)) ) {
return $end[$infomation];
}
}
selectValueFromArrayRange($number, $firstArray, $secondValue, 'value', 'infomation')

Related

get an array element where another element is known?

Array
(
[0] => Array
(
[what] => b4
[map] => 74,76,77,83
)
[1] => Array
(
[what] => b2
[map] => 53,82
)
[2] => Array
(
[what] => b1
[map] => 36
)
)
abc('b4');
function abc($what){
$map = // element `map` where `what` = $what;
}
So I need to get map where what is equal to $what;
For example - if $what is b4 result should be 74,76,77,83; and so on.
How can I do this?
If you are going to access the data on a regular basis and the what is unique, then use array_column() with the third parameter as the column to use as the key. Then your array is easily access with what and no loops are harmed in this answer...
$array = Array
(
Array
(
"what" => "b4",
"map" => "74,76,77,83"
),
Array
(
"what" => "b2",
"map" => "53,82"
),
Array
(
"what" => "b1",
"map" => "36"
)
);
$array = array_column($array, null, "what");
echo $array['b4']['map'];
gives...
74,76,77,83
With array_search() and array_column() you can get the matching $map in one line:
<?php
$array = Array
(
Array
(
"what" => "b4",
"map" => "74,76,77,83"
),
Array
(
"what" => "b2",
"map" => "53,82"
),
Array
(
"what" => "b1",
"map" => "36"
)
);
function abc($array, $what) {
return $array[array_search($what, array_column($array, 'what'))]['map'];
}
echo abc($array, "b4");
The function de-constructed and explained:
function abc($array /* the complete input array */, $what /* the search string */) {
// get the key of the sub-array that has $what in column 'what':
$key = array_search($what, array_column($array, 'what'));
// use that key to get 'map' on index $key
return $array[$key]['map'];
}
A working fiddle can be found here: https://3v4l.org/0NpcX
I think "walking" through an array is easy to read and understand:
<?php
$map = [
[
'what' => "b4",
'map' => "74,76,77,83"
],
[
'what' => "b2",
'map' => "53,82"
],
[
'what' => "b1",
'map' => "36"
]
];
function lookupWhatInMap(&$map, $what) {
array_walk($map, function($entry, $key) use ($what) {
if ($entry['what'] == $what) {
print_r($entry['map']);
}
});
}
lookupWhatInMap($map, "b4");
All you have to do is loop through your map and compare values.
function abc($what){
$map = [...];
foreach($map as $item) {
if (isset($item[$what]) ) {
return $item["map"];
}
}
return false;
}
If you just want 1 value from the array, you could use a foreach and a return statement where there is a match:
$a = [
[
"what" => "b4",
"map" => "74,76,77,83"
],
[
"what" => "b2",
"map" => "53,82"
],
[
"what" => "b1",
"map" => "36"
]
];
function abc($what, $arrays)
{
foreach ($arrays as $array) {
if ($array['what'] === $what) {
return $array['map'];
}
}
return false;
}
echo(abc('b4', $a)); // 74,76,77,83
Demo
https://ideone.com/V9WNNx
$arr[] = [
'what' => 'b4',
'map' => '74,76,77,83'
];
$arr[] = [
'what' => 'b2',
'map' => '53,82'
];
$arr[] = [
'what' => 'b1',
'map' => '36'
];
echo abc('b4', $arr);
function abc($what, $arr){
$map = null;
$idx = array_search($what, array_column($arr, 'what'));
if ($idx !== false) {
$map = $arr[$idx]['map'];
}
return $map;
}

Multidimensional Array delete duplicated key values with condition

I have an Array Like this:
$ratesData = [
1 => [
'id' => 1,
'amount' => 2
],
0 => [
'id' => 1,
'amount' => 1
],
2 => [
'id' => 1,
'amount' => 3
],
3 => [
'id' => 2,
'amount' => 2
]
];
I want to keep the duplicated id arrays with cheapest amount, the result will be like this:
[
0 => [
'id' => 1,
'amount' => 1
],
1 => [
'id' => 2,
'amount' => 2
]
]
I have a code that works with this problem, but I'm searching an elegant way to accomplish this without all this loops:
foreach($ratesData as $firstLoopKey => $firstLoopValue) {
foreach($ratesData as $secondLoopKey => $secondLoopValue) {
if($firstLoopValue['id'] === $secondLoopValue['id'] && $firstLoopKey != $secondLoopKey ) {
if ($ratesData[$secondLoopKey]['total_amount'] > $ratesData[$firstLoopKey]['total_amount']) {
$deleteElements[] = $secondLoopKey;
}
}
}
}
if (isset($deleteElements)) {
foreach ($deleteElements as $element) {
unset($ratesData[$element]);
}
}
$ratesData = array_values($ratesData);
return $ratesData;
You can sort by amount descending and then extract the array indexing by id which will eliminate the duplicates with the lowest amount overwriting the higher:
array_multisort(array_column($ratesData, 'amount'), SORT_DESC, $ratesData);
$ratesData = array_column($ratesData, null, 'id');
Yields:
Array
(
[1] => Array
(
[id] => 1
[amount] => 1
)
[2] => Array
(
[id] => 2
[amount] => 2
)
)
I always like having the key the same as a unique id to make array access/sorting easier, but you can re-index if needed:
$ratesData = array_values($ratesData);
Some simple solution:
// your source array
$ratesData = [];
// result array
$filtered = [];
foreach ($ratesData as $v) {
$id = $v['id'];
// if this is `$id`, which is not in `$filtered` yet
// or value of `$filtered[$id]['amount']` is greater then current `$v`
// then replace `$filtered[$id]` with current `$v`
if (!isset($filtered[$id]) || $filtered[$id]['amount'] > $v['amount']) {
$filtered[$id] = $v;
}
}
echo'<pre>',print_r(array_values($filtered)),'</pre>';
Another good solution
$uniqueRates = [];
foreach ($ratesData as $rateData) {
$key = $rateData['id'];
if (!\array_key_exists($key, $uniqueRates) ||
$rateData['total_amount'] < $uniqueRates[$key]['total_amount']
) {
$uniqueRates[$key] = $rateData;
}
}
return array_values($uniqueRates);

PHP - replace array keys recursively and change values to array including old key

I've spent a while trying to get what I need from old answers but haven't quite got it (have got close though!).
I have this;
[January] => Array
(
[Tuesday] => Array
(
[foo] => Array
(
[82] => 47731
[125] => 19894
)
[bar] => Array
(
[82] => 29911
[125] => 10686
)
)
}
...and I want this;
[0] => Array
(
'key' => 'January'
'children' => Array
[0] => Array
{
'key' => 'Tuesday'
'children' => Array
[0] => Array
{
'key' => 'foo'
'values' => Array
{
[82] => 47731
[125] => 19894
}
[1] => Array
{
'key' => 'bar'
'values' => Array
{
[82] => 29911
[125] => 10686
}
}
)
}
I've got fairly close by adapting the first answer from Recursively change keys in array but only the bottom layer of my result is correct - the nodes with keys 'Tuesday', 'foo' and 'bar' just look the same as in the source array.
Here's what I've got so far;
public function transform_hierarchical_output(&$var)
{
if (is_array($var))
{
$final = [];
$i = 0;
foreach ($var as $k => &$v)
{
$new_node = [
'key' => $k,
'children' => $v
];
$k = $i;
$this->transform_hierarchical_output($v);
$final[$k] = $new_node;
$i++;
}
$var = $final;
}
elseif (is_string($var))
{
}
}
This needs to work with a source array of any length and depth.
Thanks in advance.
Geoff
<?php
$array = [
'January' => [
'Tuesday' => [
'foo' => [
82 => 47731,
125 => 19894,
],
'bar' => [
82 => 47731,
125 => 19894,
]
]
]
];
function transform(array $input)
{
$output = [];
foreach ($input as $key => $val) {
if (is_array(array_values($val)[0])) { // if next depth is an array
$output[] = [
'key' => $key,
'children' => transform($val)
];
} else {
$output[] = [
'key' => $key,
'values' => $val
];
}
}
return $output;
}
print_r(transform($array));
try below:
function t($arr)
{
$a = [];
$num = 0;
foreach($arr as $k => $v) {
if (is_array($v))
{
$a[$num] = [
'key' => $k,
];
$a[$num][is_array(array_values($v)[0]) ? 'children' : 'values'] = t($v);
$num ++;
} else {
$a[$k] = $v;
}
}
return $a;
}
First thing I should note is that, though there are many recursions in your example, but technically it is not a recursive loop in terms of the need for a self-executing function. Because your loop's scheme fluctuates a bit in its depth, it does not follow a regular pattern down to is last node; however it is a logical scheme, but is not repeated down to is last node.
The following function might work for you:
function doArray($array)
{
$keys = array_keys($array);
$arr_count = count($keys);
$new_array;
for($i = 0; $i < $arr_count; $i++)
{
$new_array[$i]["key"] = $keys[$i];
$new_keys = array_keys($array[$keys[$i]]);
for($w = 0; $w < count($new_keys); $w++)
{
$new_array[$i]["children"][$w]["keys"] = $new_keys[$i];
$new_array[$i]["children"][$w]["children"] = array();
for($w = 0; $w < count($new_keys); $w++)
{
$new_new_keys = array_keys($array[$keys[$i]][$new_keys[$w]]);
for($q = 0; $q < count($new_new_keys); $q++)
{
$new_array[$i]["children"][$w]["children"][$q]["key"] = $new_new_keys[$q];
//$new_array[$i]["children"][$w]["children"][$q]["children"] = $array[$keys[$i]][$new_keys[$w]][$new_new_keys[$q]];
$last_new_keys = array_keys($array[$keys[$i]][$new_keys[$w]][$new_new_keys[$q]]);
for($s = 0; $s < count($last_new_keys); $s++)
{
$new_array[$i]["children"][$w]["children"][$q]["values"][$last_new_keys[$s]] = $array[$keys[$i]][$new_keys[$w]][$new_new_keys[$q]][$last_new_keys[$s]];
}
}
}
}
}
return $new_array;
}

How do I reform this array into a differently structured array

I have an array that looks like this:
[0] => Array
(
[name] => typeOfMusic
[value] => this_music_choice
)
[1] => Array
(
[name] => myMusicChoice
[value] => 9
)
[2] => Array
(
[name] => myMusicChoice
[value] => 8
)
I would like to reform this into something with roughly the following structure:
Array(
"typeOfMusic" => "this_music_choice",
"myMusicChoice" => array(9, 8)
)
I have written the following but it doesn't work:
foreach($originalArray as $key => $value) {
if( !empty($return[$value["name"]]) ){
$return[$value["name"]][] = $value["value"];
} else {
$return[$value["name"]] = $value["value"];
}
}
return $return;
I've tried lots of different combinations to try and get this working. My original array could contain several sets of keys that need converting to arrays (i.e. it's not always going to be just "myMusicChoice" that needs converting to an array) ?
I'm getting nowhere with this and would appreciate a little help. Many thanks.
You just need to loop over the data and create a new array with the name/value. If you see a repeat name, then change the value into an array.
Something like this:
$return = array();
foreach($originalArray as $data){
if(!isset($return[$data['name']])){
// This is the first time we've seen this name,
// it's not in $return, so let's add it
$return[$data['name']] = $data['value'];
}
elseif(!is_array($return[$data['name']])){
// We've seen this key before, but it's not already an array
// let's convert it to an array
$return[$data['name']] = array($return[$data['name']], $data['value']);
}
else{
// We've seen this key before, so let's just add to the array
$return[$data['name']][] = $data['value'];
}
}
DEMO: https://eval.in/173852
Here's a clean solution, which uses array_reduce
$a = [
[
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
],
[
'name' => 'myMusicChoice',
'value' => 9
],
[
'name' => 'myMusicChoice',
'value' => 8
]
];
$r = array_reduce($a, function(&$array, $item){
// Has this key been initialized yet?
if (empty($array[$item['name']])) {
$array[$item['name']] = [];
}
$array[$item['name']][] = $item['value'];
return $array;
}, []);
$arr = array(
0 => array(
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
),
1 => array(
'name' => 'myMusicChoice',
'value' => 9
),
2 => array(
'name' => 'myMusicChoice',
'value' => 8
)
);
$newArr = array();
$name = 'name';
$value = 'value';
$x = 0;
foreach($arr as $row) {
if ($x == 0) {
$newArr[$row[$$name]] = $row[$$value];
} else {
if (! is_array($newArr[$row[$$name]])) {
$newArr[$row[$$name]] = array();
}
array_push($newArr[$row[$$name]], $row[$$value]);
}
$x++;
}

Map data from one multidimensional array to another based on shared id value

Here are two example of the format of the Arrays, full code and array content in my code below.
ARRAY 1
[
'version' => '1.0',
'injuries' => [
'timestamp' => 1377702112,
'week' => 1,
'injury' => [
[
'status' => 'Questionable',
'id' => '10009',
'details' => 'Shoulder'
],
[
'status' => 'Questionable',
'id' => '10012',
'details' => 'Ankle'
]
]
]
]
ARRAY 2
[
'version' => '1.0',
'players' => [
'timestamp' => 1377676937,
'player' => [
[
'position' => 'TMDL',
'name' => 'Bills, Buffalo',
'id' => '0251',
'team' => 'BUF'
],
[
'position' => 'TMDL',
'name' => 'Colts, Indianapolis',
'id' => '10009',
'team' => 'IND'
]
]
]
]
What I need to do is sort through both Arrays and finding matching values for the ID key. I need to then combine the values of both arrays into one array so I can print it out on screen. There is two API's provided, one for the injuries report with a player [id] key and the other for the Players Information with [id] keys. Here is how far I have gotten on this problem:
<?php
function injuries_report() {
//Get json files
$injuryData = file_get_contents('http://football.myfa...=1&callback=');
$playerData = file_get_contents('http://football.myfa...L=&W=&JSON=1');
//format json data into an array
$obj1 = json_decode($injuryData, true);
$obj2 = json_decode($playerData, true);
//return print_r($obj1); //print obj1 to see output
return print_r($obj2); //print obj2 to see output
}
?>
<!--get injuries report -->
<pre><?php injuries_report(); ?></pre>
Here's the working code, thanks to Chris:)
$injuryData = file_get_contents('http://football.myfantasyleague.com/2013/export?TYPE=injuries&L=&W=&JSON=1&callback=');
$array1 = json_decode($injuryData, true);
$playerData = file_get_contents('http://football.myfantasyleague.com/2013/export?TYPE=players&L=&W=&JSON=1');
$array2 = json_decode($playerData, true);
function map($x) {
global $array1;
if(isset($x['id'])) {
$id = $x['id'];
$valid = array_filter($array1['injuries']['injury'], create_function('$injury', 'return $injury["id"] == "' . $id .'";'));
if(count($valid) > 0) {
$x = array_merge($x, array_shift($valid));
}
}
return $x;
}
$output = array_map('map', $array2['players']['player']);
echo "<pre>";
print_r($output);
echo "</pre>";
Ok, I'm assuming you want to add injuries to players. The output will be the list of players, with the injuries added (where they apply)
$output = array_map(function($x) use ($array1) {
$id = $x['id'];
$valid = array_filter($array1['injuries']['injury'], function($injury) use ($id) {
return $injury['id'] == $id;
});
if(count($valid) > 0) {
$x = array_merge($x, $valid[0]);
}
return $x;
}, $array2['players']['player']);
print_r($output);
The output is this:
Array
(
[0] => Array
(
[position] => TMDL
[name] => Bills, Buffalo
[id] => 0251
[team] => BUF
)
[1] => Array
(
[position] => TMDL
[name] => Colts, Indianapolis
[id] => 10009
[team] => IND
[status] => Questionable
[details] => Shoulder
)
)
php 5.2
Edit The latest working version:
Oh you are using php 5.2. Here is a php 5.2 version, but it less pretty than the code before:
$injuryData = file_get_contents('http://football.myfantasyleague.com/2013/export?TYPE=injuries&L=&W=&JSON=1&callback=');
$array1 = json_decode($injuryData, true);
$playerData = file_get_contents('http://football.myfantasyleague.com/2013/export?TYPE=players&L=&W=&JSON=1');
$array2 = json_decode($playerData, true);
function map($x) {
global $array1;
if(isset($x['id'])) {
$id = $x['id'];
$valid = array_filter($array1['injuries']['injury'], create_function('$injury', 'return $injury["id"] == "' . $id .'";'));
if(count($valid) > 0) {
$x = array_merge($x, array_shift($valid));
}
}
return $x;
}
$output = array_map('map', $array2['players']['player']);
print_r($output);
The $array1 is global here. Check it here: http://pastebin.com/N3RqtfzN

Categories