Sorting PHP array based on different array - php

So I've searched for hours but no thread seems to get me to a working solution.
My problem;
I've got 2 arrays. 1 array with the user's roles. And one array with all roles with an specific order.
$roles = Array
(
[0] => Array
(
[id] => 22465
[name] => Rank 1
[position] => 24
[color] => 16711680
)
[1] => Array
(
[id] => 59454
[name] => Rank 2
[position] => 15
[color] => 15844367
)
[2] => Array
(
[id] => 62280
[name] => Rank 3
[position] => 2
[color] => 65494
)
[3] => Array
(
[id] => 67139
[name] => Rank 4
[position] => 10
[color] => 1146986
)
[4] => Array
(
[id] => 75372
[name] => Rank 5
[position] => 25
[color] => 1146986
)
[5] => Array
(
[id] => 75373
[name] => Rank 6
[position] => 18
[color] => 1146986
)
...
)
And I have the user roles array:
$userdata = Array
(
[roles] => Array
(
[0] => 22465
[1] => 59454
[2] => 62280
[3] => 67139
[4] => 75372
[5] => 75373
)
[data] => Array
(
[0] => irrelevant
)
)
I want the user roles array to be sorted to the roles 'position' in the other array.
I think the bottleneck is in the part that the array has to be called with the subarray [roles][position] to get the order to work.
The result should be:
[0] => 75372
[1] => 22465
[2] => 75373
[3] => 59454
[4] => 67139
[5] => 62280
Could you please help me any further?
Thanks in advance!

// First, build a lookup table relating id directly to position
$ranks = [];
foreach($roles as $role) {
$ranks[$role['id']] = $role['position'];
}
var_dump($ranks);
// Now sort the table using the lookup table we just produced
//
usort($userdata['roles'], function($a, $b) use ($ranks){
return $ranks[$b] <=> $ranks[$a];
});
var_dump($userdata);
Content of userdata array after sorting
array (size=2)
'roles' =>
array (size=6)
0 => int 75372
1 => int 22465
2 => int 75373
3 => int 59454
4 => int 67139
5 => int 62280
'data' =>
array (size=1)
0 => string 'irrelevant' (length=10)

Related

Issue in merge array and delete duplicate all array

I've merged two arrays. A duplicate entry is a deleted. Let me explain the as an example (I have compare array using user_id)
$array1 = Array
(
[0] => Array
(
[id] => 44
[user_id] => 2
[name] => jina_testl
[profilePhoto] =>
)
)
$array2 = Array
(
[0] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[1] => Array
(
[id] => 3
[user_id] => 2
[name] => abc
[profilePhoto] =>
)
[2] => Array
(
[id] => 4
[user_id] => 4
[name] => test
[profilePhoto] =>
)
)
I have merged array1 and array2 and duplicate array remove. I get the following output:
Array
(
[0] => Array
(
[id] => 44
[user_id] => 2
[name] => jina_testl
[profilePhoto] =>
)
[1] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[3] => Array
(
[id] => 4
[user_id] => 4
[name] => abc
[profilePhoto] =>
))
But I want such an output like this:
Array
(
[0] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[1] => Array
(
[id] => 4
[user_id] => 4
[name] => abc
[profilePhoto] =>
))
You could do something like the following: first get all the user_ids that we do not want to be included, by taking the intersection of the two columns.
If we then merge the two separate arrays and exclude the ones that are present in the array of unwanted IDs we should get our final result.
$userId = 'user_id';
$userIdsArray1 = array_column($array1, $userId);
$userIdsArray2 = array_column($array2, $userId);
// If we then take the negation we should get something similar to an exclusive or.
// Thus those in one or the other but not in both arrays.
$unwantedUserIds = array_intersect($userIdsArray1, $userIdsArray2);
$result = [];
foreach (array_merge($array1, $array2) as $record) {
if (!in_array($record[$userId], $unwantedUserIds)) {
$result[] = $record;
}
}
echo '<pre>', print_r($result, true), '</pre>';
Result:
Array
(
[0] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[1] => Array
(
[id] => 4
[user_id] => 4
[name] => test
[profilePhoto] =>
)
)

Joining two multidimensional arrays

I have two arrays each coming from different DB queries, I can't join them in DB so I have to join them using php.
The first:
Array
(
[0] => Array
(
[id] => 23
[host_id] => 5
[pos_id] => 2
[status] => 1
)
[1] => Array
(
[id] => 25
[host_id] => 5
[pos_id] => 1
[status] => 1
)
[2] => Array
(
[id] => 24
[host_id] => 5
[pos_id] => 2
[status] => 1
)
)
And I wanna join it with this array on pos_id and id
Array
(
[0] => Array
(
[id] => 1
[name] => Front
)
[1] => Array
(
[id] => 2
[name] => Back
)
)
so that, the result is:
Array
(
[0] => Array
(
[id] => 23
[host_id] => 5
[pos_id] => 2
[name] => Back
[status] => 1
)
[1] => Array
(
[id] => 25
[host_id] => 5
[pos_id] => 1
[name] => Front
[status] => 1
)
[2] => Array
(
[id] => 24
[host_id] => 5
[pos_id] => 2
[name] => Back
[status] => 1
)
)
The code I have uses an inner loop, matches the value and pushes into array:
foreach($events as &$event) {
foreach($positions as $position) {
if($player[pos_id] == $position[id]){
array_push($event,"name",$position[name]);
}
}
}

Sort array keys (numeric) to specific order array (numeric)

I want to change order of following array to 2nd array's values.
Array
(
[2] => Array
(
[title] => Photometric Interpretation
[name] => photometric_interpretation
)
[3] => Array
(
[title] => Make
[name] => make
)
[4] => Array
(
[title] => Model
[name] => model
)
[5] => Array
(
[title] => Strip Offsets
[name] => strip_offsets
)
[6] => Array
(
[title] => Samples Per Pixel
[name] => samples_per_pixel
)
[7] => Array
(
[title] => Rows Per Strip
[name] => rows_per_strip
)
)
I want to change order of above to following array's values.
Array
(
[0] => 3
[1] => 4
[2] => 7
[3] => 6
[4] => 5
[5] => 2
)
What I have tried
$index = array_flip(['3,4,7,6,5,2']);
$assigned_fields = array_merge($fisrt_array, $index);
My desired output is
Array
(
[3] => Array
(
[title] => Make
[name] => make
)
[4] => Array
(
[title] => Model
[name] => model
)
[7] => Array
(
[title] => Rows Per Strip
[name] => rows_per_strip
)
[6] => Array
(
[title] => Samples Per Pixel
[name] => samples_per_pixel
)
[5] => Array
(
[title] => Strip Offsets
[name] => strip_offsets
)
[2] => Array
(
[title] => Photometric Interpretation
[name] => photometric_interpretation
)
)
This should work fine.
$a = ['2' => ['title' => 'Photometric Interpretation',
'name' => 'photometric_interpretation'],
'3' => ['title' => 'Make',
'name' => 'make']];
$b = Array
(
0 => 3,
1 => 2
);
$c = [];
foreach($b as $s) {
$c[$s] = $a[$s];
}
print_r($c);
You need to use array_replace instead of array_merge.
$assigned_fields = array_replace(array_flip($index), $fisrt_array);

PHP add arrays to an array on a specific element

I am trying to merge 2 arrays a single array on a multidimensional array where a given key-value = a value
the first array looks like this:
Array
(
[0] => Array
(
[id] => 4
[subcategories] => Array
(
[0] => Array
(
[id] => 5
[category_order] => 0
[parent_id] => 4
[name] => Audio Equipment
)
[1] => Array
(
[id] => 6
[category_order] => 0
[parent_id] => 4
[name] => Home Entertainment
)
[2] => Array
(
[id] => 7
[category_order] => 0
[parent_id] => 4
[name] => Photography
)
[3] => Array
(
[id] => 8
[category_order] => 0
[parent_id] => 4
[name] => Portable Audio
)
[4] => Array
(
[id] => 9
[category_order] => 0
[parent_id] => 4
[name] => Televisions
)
)
)
)
and the second like this:
Array
(
[0] => Array
(
[id] => 10
[parent_id] => 5
[name] => Amplifiers & Receivers
)
[1] => Array
(
[id] => 11
[parent_id] => 5
[name] => Audio Systems
)
[2] => Array
(
[id] => 12
[parent_id] => 5
[name] => Cassette Decks
)
[3] => Array
(
[id] => 13
[parent_id] => 5
[name] => CD Players
)
[4] => Array
(
[id] => 14
[parent_id] => 5
[name] => Radios
)
[5] => Array
(
[id] => 15
[parent_id] => 5
[name] => HiFi Speakers
)
)
What I want to do is add each of the second arrays to a sub array of the first multidimensional array where the parent_id of the second array = the id of the subcategories array of the first array so it will look like this:
array
(
[0]=> Array
(
[id] => 4
[subcategories] => Array
(
[0] => Array
(
[id] => 5
[category_order] => 0
[parent_id] => 4
[name] => Audio Equipment
[subsubcategories] = array
(
[id] => 10
[parent_id] => 5
[name] => Amplifiers & Receivers
)
)
Something like this should work just rename the array names because you didn't provide them. But I think you'll get the idea :) Mainly you loop through all subcategories with foreach loop or another you'll get the parent id and can access the main array with that parent id and save the sub categories info in there.
foreach( $sub_array as $item ) {
$main_array[ category_id ][ $item[ 'parent_id' ] ][ 'subsubcategories' ] = $item;
}

I can't get Set::sort working on lower levels

In my app, I have the following Models and relationships:
ActiveMember belongsTo Team
ActiveMember belongsTo Rank
ActiveMember hasMany ContactInfo
ContactInfo belongsTo ContactType
In my controller, I am them doing a contained find as so;
$this->Team->contain(array(
'ActiveMember' => array (
'fields' => array('id','surname','firstname'),
'Rank' => array(
'fields' => array('id','display','position')) ,
'ContactInfo' => array (
'ContactType',
'conditions' => 'contact_type_id IN (1, 2, 3, 4)'
)
)
)
);
$Teams = $this->Team->find('all', array('conditions' => 'Team.active = 1 AND Team.display_order<99'));
This then returns an array like this:
Array
(
[0] => Array
(
[Team] => Array
(
[id] => 3
[name] => Command
[display_order] => 1
[active] => 1
)
[ActiveMember] => Array
(
[0] => Array
(
[id] => 1
[surname] => Bloggs
[firstname] => Joe
[rank_id] => 1
[team_id] => 3
[Rank] => Array
(
[id] => 1
[display] => Commander
[position] => 1
)
[ContactInfo] => Array
(
[0] => Array
(
[id] => 2
[member_id] => 1
[contact_type_id] => 1
[info] => 1234 5678
[ContactType] => Array
(
[id] => 1
[name] => Home Phone
[format] => #### ####
)
)
)
)
[1] => Array
(
[id] => 3
[surname] => Smith
[firstname] => Jane
[rank_id] => 2
[team_id] => 3
[Rank] => Array
(
[id] => 2
[display] => Dep Comm
[position] => 10
)
[ContactInfo] => Array
(
)
)
)
)
[1] => Array
(
[Team] => Array
(
[id] => 1
[name] => Support
[display_order] => 2
[active] => 1
)
[ActiveMember] => Array
(
[0] => Array
(
[id] => 124
[surname] => Johnson
[firstname] => John
[rank_id] => 6
[team_id] => 1
[Rank] => Array
(
[id] => 6
[display] => Member
[position] => 50
)
[ContactInfo] => Array
(
)
)
And then I want to sort the result as per 'ORDER BY Team.display_order, Team.Member.Rank.position, Team.Member.surname, Team.Member.firstname'
Given that I can't do this complex sort in the query without doing adhoc joins, I thought I could use Set::sort, called four times to sort the order.
$Teams = Set::sort($Teams,'{n}.ActiveMember.{n}.surname','asc');
$Teams = Set::sort($Teams,'{n}.ActiveMember.{n}.firstname','asc');
$Teams = Set::sort($Teams,'{n}.ActiveMember.{n}.Rank.position','asc');
$Teams = Set::sort($Teams,'{n}.Team.display_order','asc');
However, despite the Set path of the first three lines returning correct values if I do a Set::extract, they do not have any effect on the array order (either when called as a group, or as the only sort). The final line works.
Can someone please advise where my mistake is, or another way to achieve the same result?

Categories