Effective and elegant way to get an item from array - php

For example, i've got an array like this:
$a = array(
0 => array(
'foo' => 42
),
1 => array(
'foo' => 143
),
2 => array(
'foo' => 4
)
);
And i need to get an element with a maximum value in 'foo'. Current code is this:
$foos = array_map(function($v) {
return $v['foo'];
}, $a);
$keys = array_keys($foos, max($foos));
$winner = $a[$keys[0]];
print_r($winner);
Which is a scary thing.

You can try with:
$input = array(
array('foo' => 42),
array('foo' => 143),
array('foo' => 4),
);
$output = array_reduce($input, function($a, $b) {
return $a['foo'] > $b['foo'] ? $a : $b;
});
Output:
array (size=1)
'foo' => int 143

Most elegant?
$maxValue = max($a);
http://www.php.net/manual/en/function.max.php
Works even with multi-dimensional:
<?php
$a = array(
0 => array(
'foo' => 42
),
1 => array(
'foo' => 143
),
2 => array(
'foo' => 4
)
);
$maxValue = max($a);
print_r($maxValue["foo"]);
echo $maxValue["foo"];
Output with echo 143.
Output with print_r() Array ( [foo] => 143 )

Just run the foreach yourself. Readable and easy.
$highest_foo = PHP_INT_MIN;
$result = null;
foreach ($a as $key=>$foo) {
if ($foo['foo'] > $highest_foo) {
$result = $a[$key];
$highest_foo = $foo['foo'];
}
}
print_r($result);

$array = array(
0 => array(
'foo' => 42
),
1 => array(
'foo' => 143
),
2 => array(
'foo' => 4
)
);
$maxs = array_keys($array, max($array));
print_r(max($array));//Highest value
print_r($maxs);//Key of hishest value

Related

PHP sort array of objects by two properties

I have an array
Array
(
[0] => stdClass Object
(
[tab_option_name_selector] => 2
[fieldtype] => notes
[order] => 12
)
[1] => stdClass Object
(
[tab_option_name_selector] => 2
[fieldtype] => notes
[order] => 8
)
[2] => stdClass Object
(
[tab_option_name_selector] => 1
[order] => 2
[fieldtype] => selectbox
)
[3] => stdClass Object
(
[tab_option_name_selector] => 2
[order] => 3
[fieldtype] => selectbox
)
)
I'm trying to get this usort function to work
function osort(&$array, $props)
{
if(!is_array($props))
$props = array($props => true);
$me = usort($array, function($a, $b) use ($props) {
foreach($props as $prop => $ascending)
{
if($a->$prop != $b->$prop)
{
if($ascending)
return $a->$prop > $b->$prop ? 1 : -1;
else
return $b->$prop > $a->$prop ? 1 : -1;
}
}
return -1; //if all props equal
});
print_r($props);
return ($me);
}
$tab = osort($objectArray, "tab_option_name_selector", "order");
so sorting by the tab then order.
$tab is empty - any ideas what I'm doing wrong?
Why the extra level of indirection and making things more confusing? Why not usort directly with usort($objectArray, "sortObjects"); using a sortObjects($a,$b) function that does what any comparator does: return negative/0/positive numbers based on the input?
If the tabs differ, return their comparison, if they're the same, return the order comparison; done.
$array = array(
(object)array(
'tab_option_name_selector' => 2,
'fieldtype' => 'notes',
'order' => 12
),
(object)array(
'tab_option_name_selector' => 2,
'fieldtype' => 'notes',
'order' => 8
),
(object)array(
'tab_option_name_selector' => 1,
'order' => 2,
'fieldtype' => 'selectbox'
),
(object)array(
'tab_option_name_selector' => 2,
'order' => 3,
'fieldtype' => 'selectbox'
)
);
function compareTabAndOrder($a, $b) {
// compare the tab option value
$diff = $a->tab_option_name_selector - $b->tab_option_name_selector;
// and return it. Unless it's zero, then compare order, instead.
return ($diff !== 0) ? $diff : $a->order - $b->order;
}
usort($array, "compareTabAndOrder");
print_r($array);
Why don't you use array_multisort? http://php.net/manual/de/function.array-multisort.php
$data = //your array
//Create independent arrays
foreach ($data as $row) {
foreach ($row as $key => $value){
${$key}[] = $value;
//Creates $tab_option_name_selector, $fieldtype and $order array
//in order to use them as independent arrays in array_multisort.
}
}
array_multisort($tab_option_name_selector, SORT_ASC, $order, SORT_ASC, $data);
//$data sorted as expected.
echo "<pre>";
print_r($data);
echo "</pre>";
An example for unlimited number of properties:
$data = [
(object)['volume' => '1', 'edition' => '1'],
(object)['volume' => '2', 'edition' => '1'],
(object)['volume' => '3', 'edition' => '10'],
(object)['volume' => '3', 'edition' => '50'],
(object)['volume' => '3', 'edition' => '20'],
(object)['volume' => '4', 'edition' => '3'],
];
// sorting list by properties
$sorting = ['volume' => SORT_DESC, 'edition' => SORT_ASC];
$arrays = [];
foreach ($sorting as $key => $sort) {
$column = array_column($data, $key);
if (!empty($column)) {
$arrays[] = $column;
$arrays[] = $sort;
}
}
if (!empty($arrays)) {
$arrays[] = $data;
if (!array_multisort(...$arrays)) {
var_dump('some error');
die();
}
// get last array, that is the sorted data
$data = ($arrays[array_key_last($arrays)]);
}
Example partially from php.net - array_multisort

Find array elements that have a certain key-name prefix

I have an associative array with lots of elements and want to get a list of all elements that have a key name with a certain prefix.
Example:
$arr = array(
'store:key' => 1,
'user' => 'demo',
'store:foo' => 'bar',
'login' => true,
);
// this is where I need help with:
// the function should return only elements with a key that starts with "store:"
$res = list_values_by_key( $arr, 'store:' );
// Desired output:
$res = array(
'store:key' => 1,
'store:foo' => 'bar',
);
You could simply do :
$arr = array(
'store:key' => 1,
'user' => 'demo',
'store:foo' => 'bar',
'login' => true,
);
$arr2 = array();
foreach ($arr as $array => $value) {
if (strpos($array, 'store:') === 0) {
$arr2[$array] = $value;
}
}
var_dump($arr2);
Returns :
array (size=2)
'store:key' => int 1
'store:foo' => string 'bar' (length=3)
This should work for you:
Just grab all keys which starts with store: with preg_grep() from your array. And then do a simple array_intersect_key() call to get the intersect of both arrays.
<?php
$arr = array(
'store:key' => 1,
'user' => 'demo',
'store:foo' => 'bar',
'login' => true,
);
$result = array_intersect_key($arr, array_flip(preg_grep("/^store:/", array_keys($arr))));
print_r($result);
?>
output:
Array
(
[store:key] => 1
[store:foo] => bar
)
From php 5.6 you can use array_filter:
$return = array_filter($array, function ($e) {
return strpos($e, 'store:') === 0;
}, ARRAY_FILTER_USE_KEY);
var_dump($return);
for earlier versions, you can use
$return = array_intersect_key($array, array_flip(array_filter(array_keys($array), function ($e) {
return strpos($e, 'store:') === 0;
})));
Demo.

Compare element in array and loop through each php

I want to compare a value of data to a list of element which I had retrieved from php array(decoded json).
First,
This is the first array:
Array1
(
[0] => Array
(
[member_id] => 3
[member_card_num] => 2013011192330791
[member_barcode] => 2300067628912
)
[1] => Array
(
[member_id] => 4
[member_card_num] => 2328482492740000
[member_barcode] => 3545637000
)
[2] => Array
(
[member_id] => 2
[member_card_num] => 40001974318
[member_barcode] => 486126
)
[3] => Array
(
[member_id] => 1
[member_card_num] => 91001310000057698
[member_barcode] => 000057698
)
)
This is the second Array:
Array2
(
[0] => Array
(
[member_id] => 2
[member_card_num] => 40001974318
[member_barcode] => 486126
)
)
Second,
I had retrieved the (member_barcode) which I required.
Here is the code:
For Array1:
foreach ($decode1 as $d){
$merchant_barcode = $d ['member_barcode'];
echo $merchant_barcode;
}
For Array2:
foreach ($decode2 as $d2){
$user_barcode = $d2 ['member_barcode'];
echo $user_barcode;
}
Then,
I get this output():
For Array1(merchant_barcode):
2300067628912
3545637000
486126
000057698
For Array2(user_barcode):
486126
The question is, I would to check and compare whether the user_barcode in Array2(486126) is exist/match to one of the merchant_barcode in Array1.
This is my code,
but it only compare the user_barcode in Array2 to the last element(000057698) in Array1,
I want it to loop through each n check one by one. How can I do that?
public function actionCompareBarcode($user_barcode, $merchant_barcode){
if(($user_barcode) == ($merchant_barcode)){
echo "barcode exist. ";
}
else{
echo "barcode not exist";
}
}
In this case, the output I get is "barcode not exist", but it should be "barcode exist".
Anyone can help? Appreciate that. Im kinda new to php.
You could use a nested loop like:
foreach ($decode2 as $d2)
{
$user_barcode = $d2 ['member_barcode'];
foreach ($decode1 as $d)
{
$merchant_barcode = $d ['member_barcode'];
if ($merchant_barcode == $user_barcode)
{
echo "Match found!";
}
else
{
echo "No match found!";
}
}
}
<?
$a = array(
array(
'member_id' => 3,
'member_card_num' => '2013011192330791',
'member_barcode' => '2300067628912',
),
array(
'member_id' => 4,
'member_card_num' => '2328482492740000',
'member_barcode' => '3545637000',
),
array(
'member_id' => 2,
'member_card_num' => '40001974318',
'member_barcode' => '486126',
),
array(
'member_id' => 1,
'member_card_num' => '91001310000057698',
'member_barcode' => '000057698',
)
);
$b = array(
array(
'member_id' => 2,
'member_card_num' => '40001974318',
'member_barcode' => '486126',
)
);
array_walk($a, function($item) use($b) {
echo ($b['0']['member_barcode'] == $item['member_barcode'] ? "found" : NULL);
});
?>
I'd use array_uintersect() to calculate if those multidimensional arrays have a common element:
<?php
$a = array(
array(
'member_id' => '3',
'member_card_num' => '2013011192330791',
'member_barcode' => '2300067628912',
),
array(
'member_id' => '2',
'member_card_num' => '40001974318',
'member_barcode' => '486126',
)
);
$b = array(
array(
'member_id' => '2',
'member_card_num' => '40001974318',
'member_barcode' => '486126',
)
);
$match = array_uintersect($a, $b, function($valueA, $valueB) {
return strcasecmp($valueA['member_barcode'], $valueB['member_barcode']);
});
print_r($match);
Try calling that method as you are looping through Array1 and comparing the user_barcode to every value
You can compare two array this way too:
$per_arr = array();
$permissions = array()
foreach ($per_arr as $key => $perms) {
if(isset($permissions[$key]['name'])){
echo $per_arr[$key]['name']; //matched data
}else{
echo $per_arr[$key]['name']; //not matched data
}
}

php flattening nested array

I have an array like this
$array:
{ name : xyz
version : Array[2]
{
0 : Array[2]
{
id : 1
batch : 1
}
1 : Array[2]
{
id : 2
batch : 2
}
}
}
How can I create an array like this:
$results[] =
name:xyz, version:0, id:1, batch:1
name:xyz, version:1, id:2, batch:2
I want an array where the common fields are repeated.
Do you mean:
$results = array();
$results[] = array('name' => 'xyz', 'version' => 0, 'id' => 1, 'batch' => 1);
$results[] = array('name' => 'xyz', 'version' => 1, 'id' => 1, 'batch' => 1);
Then access the first row by $results[0]['name']
Or second row by $results[1]['name']
EDIT
To convert from $array to $results, I have to assume your $array looks like this.
$array =
array('name' => 'xyz',
'version' => array(
0 => array(
'id' => 1,
'batch' => 1
),
1 => array(
'id' => 2,
'batch' => 2
)
)
);
then
$results = array();
$name = $array['name'];
foreach($array['version'] as $version => $idandbatch)
{
$results[] = array('name' => $name,
'version' => $version,
'id' => $idandbatch['id'],
'batch' => $idandbatch['batch']);
}
You can access the array
foreach($results as $values)
{
echo $values['name'];
echo $values['version'];
echo $values['id'];
echo $values['batch'];
}

Get certain elements of an array by its key

I'm sure there's a function for this:
What I have:
$myArray = array( 'foo' => 123, 'bar' => 456, 'lou' => 789, 'wuh' => 'xyz' );
$iNeed = array( 'foo', 'lou' );
How can I get the key value pairs that $iNeed:
$output = super_magic_function( $iNeed, $myArray );
// output should be array( 'foo' => 123, 'lou' => 789 );
How is that super_magic_function called (native php if possible)
$output = array_intersect_key($myArray, array_flip($iNeed));
If you need it as a function:
function super_magic_function($array, $required) {
return array_intersect_key($array, array_flip($required));
}
Output:
Array
(
[foo] => 123
[lou] => 789
)
Documentation: array_intersect_key(), array_flip()
Demo.

Categories