problems getting values in my multidimensional arrays - php

I'm having problems getting values in my multidimensional arrays php
$shop = array(
array(
Title => "rose",
Price => 1.25,
Number => 15
),
array(
Title => "daisy",
Price => 0.75,
Number => 25,
),
array(
Title => "orchid",
Price => 1.15,
Number => 7
)
);
And
$titlearray = array('rose','daisy');
And Now. I want check Compare 2 array;
If have value $titlearray in $shop return True or false.
Example:
$titlearray = array('rose','daisy'); return TRUE
$titlearray = array('rose','daisy','kool'); return FALSE
plz help me. Thanks for watching.

Seems simple enough.
$titles = array_map(function($i) {return $i['Title'];},$shop);
return !array_diff($titlearray,$titles);

Related

Array sort menu

I have the following array to show menu's based on the order the user specified.
The array is as follows:
$menuArray = [
'Main Street' => [
['/index.php', 'Home'],
['/city.php', $cityData[$user->city][0]],
['/travel.php', 'Travel'],
['/bank.php', 'Bank'],
['/inventory.php', 'Inventory'],
['/dailies.php', 'Dailies'],
],
'Activities' => [
(!$my->hospital) ? ['/hospital.php', 'Hospital'] : [],
(!$my->hospital && !$my->prison) ? ['/crime.php', 'Crime'] : [],
['/missions.php', 'Missions'],
['/achievements.php', 'Achievements'],
],
'Services' => [
['/hospital.php', 'Hospital'],
['/prison.php', 'Prison'],
['/search.php', 'Search'],
],
'Account' => [
['/edit_account.php', 'Edit Account'],
['/notepad.php', 'Notepad'],
['/logout.php', 'Logout'],
]
];
I have a column menu_order stored in the database, which has a default value of 0,1,2,3,4, but this can change per user as they will be able to change their menu to their likes.
What I'd like to achieve:
0 => Main Street
1 => Activities
2 => Services
3 => Account
4 => Communication
To get the menu order, I do
$menuOrder = explode(',', $user->menu_order);
But I'm not sure how to handle the foreach for displaying the menu.
Here's one way to do it -- use replacement rather than a sorting algorithm.
Code: (Demo)
$menuArray = [
'Main Street' => [],
'Activities' => [],
'Services' => [],
'Account' => []
];
$lookup = [
0 => 'Main Street',
1 => 'Activities',
2 => 'Services',
3 => 'Account',
4 => 'Communication'
];
$customsort = '4,2,1,3,0';
$keys = array_flip(explode(',', $customsort)); convert string to keyed array
//var_export($keys);
$ordered_keys = array_flip(array_replace($keys, $lookup)); // apply $lookup values to keys, then invert key-value relationship
//var_export($ordered_keys);
$filtered_keys = array_intersect_key($ordered_keys, $menuArray); // remove items not on the current menu ('Communication" in this case)
//var_export($filtered_keys);
$final = array_replace($filtered_keys, $menuArray); // apply menu data to ordered&filtered keys
var_export($final);
Output:
array (
'Services' =>
array (
),
'Activities' =>
array (
),
'Account' =>
array (
),
'Main Street' =>
array (
),
)
And here's another way using uksort() and a spaceship operator:
$ordered_keys = array_flip(array_values(array_replace(array_flip(explode(',', $customsort)), $lookup)));
uksort($menuArray, function($a, $b) use ($ordered_keys) {
return $ordered_keys[$a] <=> $ordered_keys[$b];
});
var_export($menuArray);
As a consequence of how your are storing your custom sort order, most of the code involved is merely to set up the "map"/"lookup" data.
You could try something like this to produce the menu:
function display_menu($menus, $m) {
if (!isset($menus[$m])) return;
echo "<ul>";
foreach ($menus[$m] as $item) {
if (!count($item)) continue;
echo "<li>{$item[1]}\n";
}
echo "</ul>";
}
$menuMap = array(0 => 'Main Street',
1 => 'Activities',
2 => 'Services',
3 => 'Account',
4 => 'Communication');
$menuOrder = explode(',', $user->menu_order);
foreach ($menuOrder as $menuIndex) {
$thisMenu = $menuMap[$menuIndex];
display_menu($menuArray, $thisMenu);
}
Small demo on 3v4l.org

Keep array rows where a column value is found in a second flat array

** I have edited this to show how I got my code to work using array_search
I have an array, $arr1 with 5 columns as such:
key id name style age whim
0 14 bob big 33 no
1 72 jill big 22 yes
2 39 sue yes 111 yes
3 994 lucy small 23 no
4 15 sis med 24 no
5 16 maj med 87 yes
6 879 Ike larg 56 no
7 286 Jed big 23 yes
This array is in a cache, not a database.
I then have a second array with a list of id values -
$arr2 = array(0=>14, 1=>72, 2=>8790)
How do I filter $arr1 so it returns only the rows with the id values in $arr2?
I got my code to work as follows:
$arr1 = new CachedStuff(); // get cache
$resultingArray = []; // create an empty array to hold rows
$filter_function = function ($row) use ($arr2) {
return (array_search($row['id'], $arr2));
};
$resultingArrayIDs = $arr1->GetIds($filter_function, $resultingArray);
This gives me two outputs: $resultingArray & $resultingArrayIDs both of which represent the intersection of the $arr1 and $arr2.
This whole task can be accomplished with just one slick, native function call -- array_uintersect().
Because the two compared parameters in the custom callback may come either input array, try to access from the id column and if there isn't one declered, then fallback to the parameter's value.
Under the hood, this function performs sorting while evaluating as a means to improve execution time / processing speed. I expect this approach to outperform iterated calls of in_array() purely from a point of minimized function calls.
Code: (Demo)
var_export(
array_uintersect(
$arr1,
$arr2,
fn($a, $b) =>
($a['id'] ?? $a)
<=>
($b['id'] ?? $b)
)
);
Something like this should do it, provided I've understood your question and data structure correctly:
$dataArray = [
[ 'key' => 0, 'id' => 14 , 'name' => 'bob' , 'style' => 'big' , 'age' => 33 , 'whim' => 'no' ],
[ 'key' => 1, 'id' => 72 , 'name' => 'jill' , 'style' => 'big' , 'age' => 22 , 'whim' => 'yes' ],
[ 'key' => 2, 'id' => 39 , 'name' => 'sue' , 'style' => 'yes' , 'age' => 111 , 'whim' => 'yes' ],
[ 'key' => 3, 'id' => 994 , 'name' => 'lucy' , 'style' => 'small' , 'age' => 23 , 'whim' => 'no' ],
[ 'key' => 4, 'id' => 15 , 'name' => 'sis' , 'style' => 'med' , 'age' => 24 , 'whim' => 'no' ],
[ 'key' => 5, 'id' => 16 , 'name' => 'maj' , 'style' => 'med' , 'age' => 87 , 'whim' => 'yes' ],
[ 'key' => 6, 'id' => 879 , 'name' => 'Ike' , 'style' => 'larg' , 'age' => 56 , 'whim' => 'no' ],
[ 'key' => 7, 'id' => 286 , 'name' => 'Jed' , 'style' => 'big' , 'age' => 23 , 'whim' => 'yes' ]
];
$filterArray = [14, 72, 879];
$resultArray = array_filter( $dataArray, function( $row ) use ( $filterArray ) {
return in_array( $row[ 'id' ], $filterArray );
} );
View this example on eval.in
However, your question appears to suggest this data might be coming from a database; is that correct? If so, perhaps it's more efficient to pre-filter the results at the database-level. Either by adding a field in the SELECT query, that represents a boolean value whether a row matched your filter ids, or by simply not returning the other rows at all.
One way is with foreach loop with array_search()
$result = [];
foreach ($arr1 as $value) { // Loop thru $arr1
if (array_search($value['id'], $arr2) !== false) { // Check if id is in $arr2
$result[] = $value; // Push to result if true
}
}
// print result
print_r($result);
As #DecentDabbler mentioned - if the data is coming out of a database, using an IN on your WHERE will allow you to retrieve only the relevant data.
Another way to filter is to use array functions
array_column extracts the value of the id column into an array
array_intersect returns the elements which are in both $arr1['id'] and $arr2
array_flip flips the resulting array such that the indices into $arr1 indicate the elements in both $arr1 and $arr2
$arr1 = [ [ 'id' => 14, 'name' => 'bob'],
['id' => 72, 'name' => 'jill'],
['id' => 39, 'name' => 'sue'],
['id' => 994, 'name' => 'lucy'],
['id' => 879, 'name'=> 'large']];
$arr2 = [ 14,72,879 ];
$intersection = array_flip(array_intersect(array_column($arr1,'id'),$arr2));
foreach ($intersection as $i) {
var_dump($arr1[$i]);;
}

MAX in PHP returning wrong value

I have an array with key and value pair. I'm building this array dynamically and below is the code.
$x[] = array('type_name' => $value->name,
'percentage'=> intval($percentage));
My intention is to get the maximum value and for that I do
max($x);
However it is returning the wrong value actually the lowest value. Following is my array. Any help would be awesome.
$x = array(
array(
'type_name' => 'type 1'
'percentage' => 10,
),
array(
'type_name' => 'type 2'
'percentage' => 15,
),
array(
'type_name' => 'type 3'
'percentage' => 45,
),
);
Thanks is advance.
From php max() documentation :
// Multiple arrays of the same length are compared from left to right
It means that if you want to compare "percentage" values first instead of "type_name" values, you'll have to change their order in the array.
So, you could build your array like this ("percentage" comes first) and it should work :
$x[] = array(
'percentage'=> intval($percentage),
'type_name' => $value->name
);
For example :
$x = array(
array(
'percentage' => 10,
'type_name' => 'type 1'
),
array(
'percentage' => 15,
'type_name' => 'type 2'
),
array(
'percentage' => 45,
'type_name' => 'type 3'
),
array(
'percentage' => 25,
'type_name' => 'type 4'
)
);
print_r(max($x));
Output :
Array
(
[percentage] => 45
[type_name] => type 3
)
Hope it helps.
You need to read how the max compares against different types of data. In your case, you are trying to compare against one of the array item i.e. percentage inside one of the item so the function max does not know to do this.
There is an example by Revo in the manual which shows you how to do this.
You are creating an array of arrays. max doesn’t know that your arrays should be compared by the 'percentage' key, so it can’t be used here.
Instead, find the maximum value yourself. For example, like this:
$maxPercentage = false;
foreach ($x as $item) {
if ($maxPercentage === false || $item['percentage'] > $maxPercentage) {
$maxPercentage = $item['percentage'];
}
}
Now, $maxPercentage will store maximum percentage. Of, if you want an item with maximum percentage, get it like this:
$maxPercentage = false;
$maxItem = false;
foreach ($x as $item) {
if ($maxPercentage === false || $item['percentage'] > $maxPercentage) {
$maxPercentage = $item['percentage'];
$maxItem = $item;
}
}

Get the intersect of tables

I have a question. So I have this array :
$a_list_id = array(
0 => 1234
1 => 739
3 => 538
);
And this array :
$a_users = array(
0 => array(
id => 15627,
name => test
),
1 => array(
id => 1234,
name => test1
),
2 => array(
id => 739,
name => test2
)
)
The result should be :
$a_response = array(
0 => array(
id => 1234,
name => test1
)
)
Because the id 1234 is in both arrays.
I try with array_intersect but not work. Can you help me please ?
Just use loops :
$a_response = array();
foreach ($a_users as $array) {
if (in_array($array['id'], $a_list_id)) {
$a_response []= $a_users;
}
}
array_intersect will only produce useful results if the values of both arrays can be cast to the same type. You've got an array of integers and another array of arrays, they can never* match so intersect will always be empty
If you want an intersection between the arrays then you have two options:
Index the arrays so their keys are the values you want to intersect and use array_intersect_key
Implement your own array comparison logic with array_uintersect and a callback function that knows the structure of the arrays being compared
example of the former:
$a_list_id = array(
1234 => 1234
739 => 739
538 => 538
);
$a_users = array(
15627 => array(
id => 15627,
name => test
),
1234 => array(
id => 1234,
name => test1
),
739 => array(
id => 739,
name => test2
)
)
var_dump (array_intersect_key ($a_users, $a_list_id));
Example of the latter:
var_dump (array_uintersect ($a_users, $a_list_id, function ($user, $id) {
return $user ["id"] - $id; // Result should be 0 if they match, as per documentation
}))
*They can be considered the same in the case where one value is integer 0 and the other is an empty array, but that's not very useful
Try the below code using array_search() function:
$a_list_id = array(1234, 538,739);
$a_users = array(
array(
'id'=> 15627,
'name' => 'test'
),
array(
'id' => 1234,
'name' => 'test1'
),
array(
'id' => 739,
'name' => 'test2'
)
);
foreach($a_users as $a_user){
if (in_array($a_user['id'], $a_list_id)) {
$a_response[array_search($a_user['id'], $a_list_id)] = $a_user;
}
}
print_r($a_response);
Have you tried using array_intersect_uassoc? http://php.net/manual/en/function.array-intersect-uassoc.php
function compare_ids($a, $b)
{
return $a - $b['id'];
}
print_r(array_intersect_uassoc($a_list_id, $a_users, "compare_ids"));

Recursively merge two arrays, or replace with latter based on a key

This should be a really easy answer and I'm probably just being thick, but I have two arrays in PHP:
$data1 = array(
array(
'qid' => 'q-prof-1-1',
'value' => 10,
),
array(
'qid' => 'q-prof-2-1',
'value' => 3,
),
);
$data2 = array(
array(
'qid' => 'q-prof-2-1',
'value' => 5,
),
array(
'qid' => 'q-prof-3-2',
'value' => 1,
),
);
And I want to result in:
$result = array(
array(
'qid' => 'q-prof-1-1',
'value' => 10,
),
array(
'qid' => 'q-prof-2-1',
'value' => 5,
),
array(
'qid' => 'q-prof-3-2',
'value' => 1,
),
);
... so that the two will be merged- but, if it finds a qid that matches another, will replace it with the latter.
I've tried a mixture of array_merge(), array_merge_recursive(), $data1 + $data2, $data2 + $data1, array_replace(), array_replace_recursive(), array_diff() etc, etc, but every options seems to return either two or four values rather than the three. And of course I've done my fair share of S.O hunting.
Any ideas? Would prefer something short and sweet to a massive iterating function of any sort!
Thanks in advance :)
Matt
Edit:
I've just realised that if I turn the arrays inside $data1 & $data2 into key-value pairs most of those merge and replace functions work, eg:
$data1 = array(
'q-prof-1-1' => array(
'qid' => 'q-prof-1-1',
'value' => 10,
) // ... etc etc
);
... but I'd still rather not have to change the original data
Is there a reason you can't use an associative array? That way you can just have
$array = array('q-prof-1-1' => 10, 'q-prof-2-1' => 3);
$array2 = array('q-prof-2-1' => 5, 'q-prof-3-2' => 1);
Then just loop through $array2, push the value on if $array doesn't have a key (key_exists() if i remember right) or if it does have a key merge them how you want?
Also, but not sure, using an associative array would probably make array_merge work correctly (possibly).

Categories