I have the following array
$data = [
[
'name' => 'Electric Khodro',
'price' => 12912
],
[
'name' => 'Iran Khodro',
'price' => 15218
],
[
'name' => 'Iran arghaam',
'price' => 8853
]
];
I want to get key of the maximum price name car from the array that is joy from the above array.
There are two tips in question:
If the value of the $ data variable was empty, the function must return the null value.
۲. The getHighestPrice function should have no parameters.
The general view of the codes is as follows:
<?php
$data = [
[
'name' => 'Electric Khodro',
'price' => 12912
],
[
'name' => 'Iran Khodro',
'price' => 15218
],
[
'name' => 'Iran arghaam',
'price' => 8853
]
,
// ...
];
function getHighestPrice()
{
// TODO: Implement
}
Thank you for helping in advance.
You can use array_column to get a one dimensional array from 'price'. php then has the function max() for the maximum.
$maxPrice = max(array_column($data,'price'));
The definition of a function only makes sense if it also uses parameters. Without parameters, you would have to work with global variables, but nobody in PHP doesn't do that.
function getHighestPrice($data,$name){
$prices = array_column($data,$name);
return $prices == [] ? NULL : max($prices);
}
$maxPrice = getHighestPrice($data,'price');
The function returns NULL if the array $data is empty or the name does not exist as a column.
Try self on 3v4l.org
As your requirement, If the getHighestPrice() function should have no parameters then you have to get the $data from global scope.
<?php
$data = [
[
'name' => 'Electric Khodro',
'price' => 12912
],
[
'name' => 'Iran Khodro',
'price' => 15218
],
[
'name' => 'Iran arghaam',
'price' => 8853
]
];
function getHighestPrice()
{
$data = $GLOBALS['data'] ?? null;// Get $data variable
if(empty($data)){
return null;// If empty then return null
}
// Sorting
usort($data, function($a, $b) {
return $a['price'] < $b['price'];
});
// Return the maximum price
return $data[0]['price'];
// Return the car name of maximum price
/*
return $data[0]['name'];
*/
}
echo getHighestPrice();
Output: 15218
I think you want the key of the highest value
$data = [
[
'name' => 'Electric Khodro',
'price' => 12912
],
[
'name' => 'Iran Khodro',
'price' => 15218
],
[
'name' => 'Iran arghaam',
'price' => 8853
]
];
echo(getHighestPrice($data));
function getHighestPrice($array = [])
{
$max = null;
$result = null;
foreach ($array as $key => $value) {
if ($max === null || $value['price'] > $max) {
$result = $key;
$max = $value['price'];
}
}
return $result;
}
OUTPUT:
1
enter image description here
Because we are sure that the data we have is not empty, we can first assume that the first cell of the given data is the maximum, so we put a variable called maxKey $ (which you put) and set it to zero.
Now in a quick h, we check if each item is worth more than the price at home maxKey $ or not, if so, we will update the value maxKey $.
Finally it is enough to return the value of data [$ maxKey] ['name'] $ (which is one of the problems with your current code is that you return the maximum value in immediate HR while there may be some more)
There is another problem with you: the value of $ key is not defined (in line 31) and also in For HH you have to compare the value of the item, which now compares the item itself, which is an associative array.
Related
I have a a number of values/IDs that need to be translated to a single ID, what is the recommended method using PHP?
For example, I want IDs 38332, 84371, 37939, 1275 to all translate to ID 1234 and IDs222, 47391, 798 to all translate to ID 1235, etc. .
I'm thinking PHP has something built-in to handle this efficiently?
I'm thinking PHP has something built-in to handle this efficiently?
You can use the standard array as a map, quickly translating one ID to another:
$table[38332]; # int(1234)
depending on how you store your overall translation table, you can create a function that returns the translation from its input:
$table = $translation('I want IDs 38332, 84371, 37939, 1275 to all translate to ID 1234');
$result = $table[1275] ?? null; # int(1234)
Example:
$parseId = static fn(string $i) => (int)trim($i);
$translation = static fn(string $buffer): array
=> preg_match_all('~((?:\d+,\s*)+\d+)\s+to all translate to ID\s*(\d+)~', $buffer, $_, PREG_SET_ORDER)
? array_reduce($_, static fn (array $carry, array $item): array => [
$ids = array_map($parseId, explode(',', $item[1])),
$carry += array_fill_keys($ids, $parseId($item[2])),
$carry,][2], []) : [];
This is pretty easy to accomplish with PHP, here's one way you could do it:
Using this method, you populate the $map array, using the id you want to replace with as the key, and the value being an array of the keys you want to be replaced. It then calculates a simple key => value array based on this to make comparison a lot quicker.
Instead of creating a copy of the data, you could use foreach ($data as &$record)
$data = [
[
'id' => 1,
'foreign_id' => 38332,
'text' => 'a'
],
[
'id' => 2,
'foreign_id' => 84371,
'text' => 'b'
],
[
'id' => 3,
'foreign_id' => 37939,
'text' => 'c'
],
[
'id' => 4,
'foreign_id' => 1275,
'text' => 'd'
],
[
'id' => 5,
'foreign_id' => 222,
'text' => 'e'
],
[
'id' => 5,
'foreign_id' => 47391,
'text' => 'f'
],
[
'id' => 5,
'foreign_id' => 798,
'text' => 'g'
]
];
$map = [
123 => [
38332,
84371,
37939,
1275
],
1235 => [
222,
47391,
798
]
];
// Calculate a map to speed things up later
$map_calc = [];
foreach ($map as $destination_id => $ids) {
foreach ($ids as $id) {
$map_calc[$id] = $destination_id;
}
}
$new_data = [];
foreach ($data as $record) {
if (isset($map_calc[$record['foreign_id']]))
$record['foreign_id'] = $map_calc[$record['foreign_id']];
$new_data[] = $record;
}
var_dump($new_data);
I've a huge problem. Somehow I need to get the variation_id from an array based on a value of a child array:
$array = [
[
'attributes' => [
'attribute_art-der-karte' => 'Rot'
],
'variation_id' => '222'
],
[
'attributes' => [
'attribute_art-der-karte' => 'Green'
],
'variation_id' => '221'
]
];
So in my case I've two things available:
The key attribute_art-der-karte
The value Rot
I found nothing here instead of a sorting. Any idea? Thanks!
Simply loop over the array and return the variation ID when your condition is met (an attribute exists with the given key and the given value):
function findVariationId(array $array, string $attrName, string $attrValue): ?string {
foreach ($array as $entry) {
if (($entry['attributes'][$attrName] ?? null) === $attrValue) {
return $entry['variation_id'];
}
}
return null;
}
Demo
You can also use array filter for this
<?php
$array = [
[
'attributes' => [
'attribute_art-der-karte' => 'Rot'
],
'variation_id' => '222'
],
[
'attributes' => [
'attribute_art-der-karte' => 'Green'
],
'variation_id' => '221'
]
];
function findByAttribute ($arr, $value) {
$result = array_filter($arr, function($elem) use($value){
return $elem['attributes']['attribute_art-der-karte'] == $value;
});
if ($result) {
return array_shift($result)['variation_id'];
}
return '';
}
var_dump(findByAttribute($array, 'Rot')); // gives '222'
var_dump(findByAttribute($array, 'a')); // returns ''
var_dump(findByAttribute($array, 'Green')); // gives 221
An additional option using array_search() and array_column():
<?php
$array = [
['attributes' => ['attribute_art-der-karte' => 'Rot'], 'variation_id' => '222'],
['attributes' => ['attribute_art-der-karte' => 'Green'], 'variation_id' => '221']
];
$key = array_search (
'Rot',
array_column(array_column($array, 'attributes'), 'attribute_art-der-karte')
);
echo "variation_id: ". (($key === false) ? 'Not found' : $array[$key]["variation_id"]);
?>
Output:
variation_id: 222
You can access the element variation_id using foreach
// One way using loops identify the non-array element
foreach($array as $ele){
if(!is_array($ele)){
print_r($ele);
}
}
// Otherway for direct calling
print_r($array['variation_id']);
I've got this PHP array:
<?php
$cities = [
'amsterdam' => $amsterdam,
'prague' => $prague,
'lisboa' => $lisboa
];
$amsterdam = [
65 => [
'table' => Object
'something' => false,
'data' => [
'foo' => 'boo',
'price' => 100
]
],
173 => [
'table' => Object
'something' => false,
'data' => [
'foo' => 'hoo',
'price' => 2500
]
],
...
];
$prague = [
132 => [
'table' => Object
'something' => false,
'data' => [
'foo' => 'boo',
'price' => 2100
]
],
956 => [
'table' => Object
'something' => false,
'data' => [
'foo' => 'hoo',
'price' => 2500
]
],
...
];
$lisboa = [
175 => [
'table' => Object
'something' => false,
'data' => [
'foo' => 'boo',
'price' => 6500
]
],
64 => [
'table' => Object
'something' => false,
'data' => [
'foo' => 'hoo',
'price' => 20
]
],
...
];
?>
and I need to sort it by the subarray value ['data']['price'] so the output is like this:
<?php
$cheapest_cities [
'lisboa' => $lisboa, // because 64->data->price is 20
'amsterdam' => $amsterdam, // beacuse 65->data->price is 100
'prague' => $prague // bacause 132->data->price is 2100
];
?>
I tried several usort combinations, but the problem is, that i never know what the subarray index will be (65, 173, 132, 956, 175, 64) in my example.
Do you have any idea how to sort it?
The data comes from database:
<?php
$amsterdam = $this->getTable()->where(['package_id' => [1,2,3]])->order('package_id')->fetchPairs('id');
$lisboa = $this->getTable()->where(['package_id' => [4,5]])->order('package_id')->fetchPairs('id');
$prague = $this->getTable()->where(['package_id' => [6]])->order('package_id')->fetchPairs('id');
return [
'amsterdam' => $amsterdam,
'lisboa' => $lisboa,
'prague' => $prague,
];
?>
Thank you
I would start by making a new array, which has the smallest price of every city as value
For this I use an array_map function which reduces the $items to the price with array_reduce
$map_prices = function($n) {
$reduce_smallest_price = function($carry, $item) {
return $item['data']['price'] < $carry
? $item['data']['price']
: $carry;
};
return array_reduce($n, $reduce_smallest_price, INF);
};
$cities_price = array_map($map_prices, $cities);
asort($cities_price);
I use this prices array to sort the original array with uksort
uksort($cities, function($a, $b) {
global $cities_price;
return strnatcmp($cities_price[$a], $cities_price[$b]);
});
Here is a live example on 3v4l: https://3v4l.org/8B9VN
Don't use usort as it will remove your keys. Use uasort.
Just a quick idea:
Inside the callback function of uasort you could search the minimum of your item e.g. via array_reduce.
array_reduce($city, function($carry, $item) {
return $carry === 0 ? $item['data']['price'] : min($carry, $item['data']['price']);
}, 0);
This snippet gets the minimum of a city array. Then it should be easy to compare the values.
Full example:
function getMinimumPrice($cityArray) {
return array_reduce($cityArray, function($carry, $item) {
return $carry === 0 ? $item['data']['price'] : min($carry, $item['data']['price']);
}, 0);
}
uasort($cities, function($city1, $city2) {
$priceCity1 = getMinimumPrice($city1);
$priceCity2 = getMinimumPrice($city2);
return $priceCity1 <=> $priceCity2;
});
I have an array with an index. The index is not static and keeps changing.
$fields = [
11 => array (
'fieldId' => 'ORStreet',
'type' => 'TEXT',
'value' => 'Postbus 52',
),
];
Index of the above one is 11. But sometimes it becomes a different number.
One thing that always stays the same is the fieldId. How can i get the index of this array by only knowing the field id.
This above array is a child of the main array called 'fields'.
In my head i have something like this:
Loop through the main array called fields > if you find an array with fieliD => ORStreet. Return the index of that array.
If its not possible to get an index this way, i wouldnt mind if I got the 'value' => 'Postbus52' key-pair.
<?php
$arr = [
[
'fieldId' => 'ORStreet',
'type' => 'TEXT',
'value' => 'Postbus 52',
],
[
'fieldId' => 'vbnm',
'type' => 'TEXT',
'value' => 'Postbus 52',
],
[
'fieldId' => 'ORStreet',
'type' => 'TEXT',
'value' => 'Postbus 52',
]
];
shuffle($arr);
foreach ($arr as $key => $value) {
if(array_key_exists("fieldId", $value) && $value["fieldId"] === "ORStreet"){
echo $key;
break;
}
}
?>
I have used shuffle method to simulate randomness of the array. Then I have loop through the array to match fieldId with specified value(ORStreet) . If it got match then the loop will terminates and display the index.
Another Way:
$filteredArr = array_pop(array_filter($arr, function ($a){
return array_key_exists("fieldId", $a) && $a["fieldId"] === "ORStreet";
}));
You can use combination of array_map() and array_flip()
$index = array_flip(array_map(function($val){
return $val["fieldId"];
}, $arr));
echo $index["ORStreet"];
// output: 11
Check result in demo
One more possibility:
$result = array_keys(
array_combine(array_keys($fields), array_column($fields, "fieldId")),
"ORStreet"
);
array_column() extracts all the fieldId values, and then array_keys() searches for your desired value, returning the relevant array keys.
Note this will return an array of keys. If you only want the first key, this will return it as an integer:
$result = array_search(
"ORStreet",
array_combine(array_keys($fields), array_column($fields, "fieldId"))
);
I have a multidimensional input array and another multidimensional array containing rules by which to filter the input array.
$array = [
'tableData' => [
[
'booking_name' => 'abc/xyz/123',
'pdg' => 'assure',
'user_area' => 'es st',
'release' => 'oss72',
'start_date' => '2017-06-20 00:00:00',
'end_date' => '2017-06-23 00:00:00',
'asset_info' => [
[
'status' => 10,
'manufacturer' => 'HP',
'model' => 'HP BL460C GEN8',
'hardware_color' => ''#0066b3'
]
],
'full_name' => 'Valay Desai',
'email_address' => 'valay#xyz.com'
],
[
'booking_name' => 'abc/xyz/123',
'pdg' => 'assure',
'user_area' => 'ls reca',
'release' => 'oss72',
'start_date' => '2017-06-20 00:00:00',
'end_date' => '2017-06-23 00:00:00',
'asset_info' => [
[
'status' => 10,
'manufacturer' => 'SUN',
'model' => 'SUN GEN8',
'hardware_color' => '#0066b3'
]
],
'full_name' => 'Chako Desai',
'email_address' => 'chako#xyz.com'
]
]
];
$filterBy = [
'booking_name' => 'abc',
'pdg' => [
['name' => 'Invalid', 'value' => 'Invalid'],
['name' => 'assure', 'value' => 'assure']
],
'user_area' => [
['name' => 'es st', 'value' => 'es st'],
['name' => 'Invalid', 'value' => 'Invalid'],
['name' => 'a&o', 'value' => 'a&o']
]
];
I understand that array_filter can be used to compare the values, but I'm not sure how to perform the multi-rule filtration on the data within tableData.
Ideal output should be the first element from tableData because it has booking_name=abc, pdg=assure and user_area=es st.
I tried with:
// bigarray is an originial array to be filtered
// filterObj is an array with multiple filter conditions
array_filter($bigarray, function ($val_array) use ($filterObj) {
$intersection = array_intersect_assoc($val_array, $filterObj);
return (count($intersection)) === count($filterObj);
});
This always returns blank array.
Update 1:
I've used below way to get objects who has visible:true. Tried similar for the asked question but couldn't able to get the ideal result.
$columnVisible = array(
'visible' => 1,
);
$visibleColumns = array_filter($passedColumns, function ($val_array) use ($columnVisible) {
$intersection = array_intersect_assoc($val_array, $columnVisible);
return (count($intersection)) === count($columnVisible);
});
How do I apply multiple filtering conditions passed as an array of arrays on an associative array of arrays?
Try this solution.
$filters = array('pdg'=>array('xyzabc'), 'user_area'=>array('ls reca'));
$filter_items = array();
foreach( $items['tableData'] as $item ){
$i=0;
$is_match = true;
foreach( $filters as $key=>$value){
//$is_match = true;
if( !in_array( $item[$key], $value) ){
$is_match = false;
break;
}
//$is_match = true;
}
if( $is_match ){
$filter_items[] = $item;
}
}
I don't think I would bother trying to wrangle array_intersect()-family functions for this task. These functions perform sorting while they iterate and this is not going to be ideal while returing pass/fail type evaluations.
I would simplify the filtering array's structure to make the processing more direct. Once the pdg and user_area rules are flattened to their most meaningful parts, just call array_filter() and write the three evaluations in a single return. This will enjoy the performance benefit of "short circuiting" so as soon as a false outcome is encountered, the false will be returned without making needless extra evaluations.
I am nesting the output inside of a tableData although I don't know if that's the exact output you desire. It is simple enough to unwrap the filtered array from the element.
Code: (Demo)
$filterBy['pdg'] = array_column($filterBy['pdg'], 'value');
$filterBy['user_area'] = array_column($filterBy['user_area'], 'value');
var_export(
[
'tableData' =>
array_filter(
$array['tableData'],
function($row) use($filterBy) {
return str_contains($row['booking_name'], $filterBy['booking_name'])
&& in_array($row['pdg'], $filterBy['pdg'])
&& in_array($row['user_area'], $filterBy['user_area']);
}
)
]
);