PHP: sort array by own value pattern - php

I have an array :
array(1) { ["myarr"]=> array(5) {
[0]=> array(2) { ["symbol"]=> string(6) "EUR" ["desc"]=> string(6) "da" }
[1]=> array(2) { ["symbol"]=> string(6) "USD" ["desc"]=> string(6) "adad" }
[2]=> array(2) { ["symbol"]=> string(6) "CHF" ["desc"]=> string(6) "das23" }
[3]=> array(2) { ["symbol"]=> string(6) "GBP" ["desc"]=> string(6) "dd12" }
[4]=> array(2) { ["symbol"]=> string(6) "NOR" ["desc"]=> string(6) "233" }
}
}
Now i need sort array by symbol in order: NOR, USD, EUR, CHF , GBP
So i wrote callback function
uasort($myarr , 'sort_myarr')
function sort_myarr($a, $b) {
static $sizes = array( 'NOR' => 0, 'USD' => 1, 'EUR' => 2, 'CHF' => 3, 'GBP' => 4);
return $sizes[$a] - $sizes[$b];
}
But doesn't sort :(

Your sort function should read
return $sizes[$a['symbol']] - $sizes[$b['symbol']];
The arguments $a and $b are items from inside your array, which in this case are themselves arrays. You have to grab the appropriate element from inside them to sort with.

Related

How to order a php array based on custom value

I have the following php array:
array(4) {
[0]=>
array(3) {
["POSITION"]=>
string(6) "Marketer"
["FIRSTNAME"]=>
string(7) "John1"
["EMAIL"]=>
string(13) "example1#mail.com"
}
[1]=>
array(3) {
["POSITION"]=>
string(10) "Designer"
["FIRSTNAME"]=>
string(6) "John2"
["EMAIL"]=>
string(29) "example2#mail.com"
}
[2]=>
array(3) {
["POSITION"]=>
string(7) "CEO"
["FIRSTNAME"]=>
string(6) "John3"
["EMAIL"]=>
string(21) "example3#mail.com"
}
[3]=>
array(3) {
["POSITION"]=>
string(10) "Developer"
["FIRSTNAME"]=>
string(5) "John4"
["EMAIL"]=>
string(25) "example4#mail.com"
}
}
I want to reorder it based on [POSITION] column as follows:
CEO
Marketer
Developer
Designer
How can I do this? Any help would be highly appreciated.
Thanks
Put the positions in an array, then use this in the comparison function in usort().
$positions = [
'CEO' => 1,
'Marketer' => 2,
'Developer' => 3,
'Designer' => 4
];
usort($array, function($a, $b) use ($positions) {
return $positions[$a['POSITION']] - $positions[$b['POSITION']];
})

Restructure an array of events in PHP combining attendees with common location

I have a PHP array that holds the dates, locations and time a person will be attending an event. It starts in this format (The original array is always delivered in date/time order):
array(2) {
[0]=>
array(2) {
["date"]=>
string(8) "1st June"
["events"]=>
array(4) {
[0]=>
array(3) {
["location"]=>
string(7) "Venue A"
["name"]=>
string(4) "Pete"
["time"]=>
string(6) "4.00pm"
}
[1]=>
array(3) {
["location"]=>
string(7) "Venue A"
["name"]=>
string(4) "John"
["time"]=>
string(6) "4.30pm"
}
[2]=>
array(3) {
["location"]=>
string(7) "Venue B"
["name"]=>
string(5) "Chris"
["time"]=>
string(6) "7.30pm"
}
[3]=>
array(3) {
["location"]=>
string(7) "Venue A"
["name"]=>
string(4) "Mark"
["time"]=>
string(6) "8.00pm"
}
}
}
[1]=>
array(2) {
["date"]=>
string(8) "2nd June"
["events"]=>
array(4) {
[0]=>
array(3) {
["location"]=>
string(7) "Venue B"
["name"]=>
string(4) "Fred"
["time"]=>
string(6) "5.00pm"
}
[1]=>
array(3) {
["location"]=>
string(7) "Venue C"
["name"]=>
string(5) "Boris"
["time"]=>
string(6) "6.00pm"
}
[2]=>
array(3) {
["location"]=>
string(7) "Venue A"
["name"]=>
string(6) "Rupert"
["time"]=>
string(6) "7.00pm"
}
[3]=>
array(3) {
["location"]=>
string(7) "Venue A"
["name"]=>
string(5) "David"
["time"]=>
string(6) "9.00pm"
}
}
}
}
What I need to do is combine this so attendees at the same location are grouped together where another attendee in a different location doesn't break up the list. So the above array would be changed to this:
array(2) {
[0]=>
array(2) {
["date"]=>
string(8) "1st June"
["events"]=>
array(3) {
[0]=>
array(2) {
["location"]=>
string(7) "Venue A"
["attendees"]=>
array(2) {
[0]=>
array(2) {
["name"]=>
string(4) "Pete"
["time"]=>
string(6) "4.00pm"
}
[1]=>
array(2) {
["name"]=>
string(4) "John"
["time"]=>
string(6) "4.30pm"
}
}
}
[1]=>
array(2) {
["location"]=>
string(7) "Venue B"
["attendees"]=>
array(1) {
[0]=>
array(2) {
["name"]=>
string(5) "Chris"
["time"]=>
string(6) "7.30pm"
}
}
}
[2]=>
array(2) {
["location"]=>
string(7) "Venue A"
["attendees"]=>
array(1) {
[0]=>
array(2) {
["name"]=>
string(4) "Mark"
["time"]=>
string(6) "8.00pm"
}
}
}
}
}
[1]=>
array(2) {
["date"]=>
string(8) "2nd June"
["events"]=>
array(3) {
[0]=>
array(2) {
["location"]=>
string(7) "Venue B"
["attendees"]=>
array(1) {
[0]=>
array(2) {
["name"]=>
string(4) "Fred"
["time"]=>
string(6) "5.00pm"
}
}
}
[1]=>
array(2) {
["location"]=>
string(7) "Venue C"
["attendees"]=>
array(1) {
[0]=>
array(2) {
["name"]=>
string(5) "Boris"
["time"]=>
string(6) "6.00pm"
}
}
}
[2]=>
array(2) {
["location"]=>
string(7) "Venue A"
["attendees"]=>
array(2) {
[0]=>
array(2) {
["name"]=>
string(6) "Rupert"
["time"]=>
string(6) "7.00pm"
}
[1]=>
array(2) {
["name"]=>
string(5) "David"
["time"]=>
string(6) "9.00pm"
}
}
}
}
}
}
So here's how I've figured out to do it juggling variables and stepping through the original array:
// $eventsArray holds the original array data a per the first example
$newArray = array();
foreach($eventsArray as $day) {
$curLocation = '';
$todaysEvents = array();
$teKey = -1;
foreach($day['events'] as $event) {
if($curLocation==$event['location']) {
$todaysEvents[$teKey]['attendees'][] = array(
'name' => $event['name'],
'time' => $event['time']
);
} else {
$todaysEvents[] = array(
'location' => $event['location'],
'attendees' => array(
array(
'name' => $event['name'],
'time' => $event['time']
)
)
);
$teKey = $teKey + 1;
}
$curLocation=$event['location'];
}
$newArray[] = array(
'date' => $day['date'],
'events' => $todaysEvents
);
}
And this works! So why am I asking a question on Stack? Because this feels awfully clunky and I'm not convinced there isn't a much more efficient way of doing it. I get the feeling I'm adding overhead here where it's not necessary.
Here's an alternative version using some PHP 7 (7.3+) features:
$resultEvents = [];
foreach ($events as ['date' => $date, 'events' => $dayEvents]) {
$resultDayEvents = ['date' => $date, 'events' => []];
foreach ($dayEvents as ['location' => $location, 'name' => $name, 'time' => $time]) {
$attendee = ['name' => $name, 'time' => $time];
if ($location === ($previousLocation ?? null)) {
$resultDayEvents['events'][array_key_last($resultDayEvents['events'])]['attendees'][] = $attendee;
} else {
$resultDayEvents['events'][] = ['location' => $location, 'attendees' => [$attendee]];
}
$previousLocation = $location;
}
$resultEvents[] = $resultDayEvents;
}
Demo: https://3v4l.org/bC4LK
You can use references like a cursor to keep track of the last event processed. Less effort to compare location and add attendees. But that comes with the complexity of getting rid of it properly.
Also, but a minor thing is to use strict comparisons... Can avoid some frustrating moments by being more predectible...
// $eventsArray holds the original array data a per the first example
$newArray = array();
foreach($eventsArray as $day) {
$todaysEvents = array();
$curEvent = null;
foreach($day['events'] as $event) {
if($curEvent===null || $curEvent['location']!==$event['location']) {
unset($curEvent);
$curEvent = array(
'location' => $event['location'],
'attendees' => array()
);
$todaysEvents[] = &$curEvent;
}
$curEvent['attendees'][] = array(
'name' => $event['name'],
'time' => $event['time']
);
}
unset($curEvent);
$newArray[] = array(
'date' => $day['date'],
'events' => $todaysEvents
);
}

combine same index of array?

I have following $_POST array
array(5) {
["addcatagory"]=>
string(8) "CATEGORY"
["reg_admin_id"]=>
string(2) "25"
["subcatagory"]=>
array(2) {
[0]=>
string(9) "SUB CAT 1"
[1]=>
string(9) "sub cat 2"
}
["subCat_Detais"]=>
array(2) {
[0]=>
string(9) "AAAAAAAAA"
[1]=>
string(8) "BBBBBBBB"
}
["submit"]=>
string(15) "Submit Catagory"
}
and
array(1) {
["subCatFile1"]=>
array(5) {
["name"]=>
array(3) {
[0]=>
string(5) "2.jpg"
[1]=>
string(5) "3.jpg"
[2]=>
string(0) ""
}
["type"]=>
array(3) {
[0]=>
string(10) "image/jpeg"
[1]=>
string(10) "image/jpeg"
[2]=>
string(0) ""
}
["tmp_name"]=>
array(3) {
[0]=>
string(18) "/var/tmp/phpN5ENy2"
[1]=>
string(18) "/var/tmp/phpRyJdcc"
[2]=>
string(0) ""
}
["error"]=>
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(4)
}
["size"]=>
array(3) {
[0]=>
int(65101)
[1]=>
int(49550)
[2]=>
int(0)
}
}
}
now what i want to achieve is combine 0 index of subcatagory and subcat_details in one array and of 1 index of subcatagory and subcat_details in second array and so on...
how can i achieve this?? is it even possible??
Expectations
array( 'name' => 'SUB CAT 1',
'details' => 'AAAAAAAAA',
'image_name'=>'2.jpg'
);
array( 'name' => 'SUB CAT 2',
'details' => 'BBBBBBB',
'image_name'=>'2.jpg'
);
This can be done with a simple foreach() loop -
$newArray = [];
foreach($_POST["subcatagory"] as $key => $value) {
$newArray[] = array("name" => $_POST["subcatagory"][$key],
"details" => $_POST["subCat_Detais"][$key]);
}
As #CharlotteDunois mentioned, you could also use an for() loop, as long as you have sequential keys, with no keys missing -
$newArray = [];
for($i=0;$i<count($_POST["subcatagory"]);$i++) {
$newArray[] = array("name" => $_POST["subcatagory"][$i],
"details" => $_POST["subCat_Detais"][$i]);
}

How to filter array to get only the object and not array in PHP

I'm not even sure what to search for for this question. What I really want is I have an array of objects like this
array(3) {
[0]=>
object(stdClass)#423 (4) {
["name"]=>
string(3) "Blah"
["full_name"]=>
string(10) "/Blah"
["id"]=>
string(32) "BlahBlah"
["parent_id"]=>
string(32) "BlahBlah"
}
[1]=>
object(stdClass)#422 (4) {
["name"]=>
string(8) "Blah1"
["full_name"]=>
string(9) "Blah2"
["id"]=>
string(32) "BlahBlah2"
["parent_id"]=>
NULL
}
[2]=>
object(stdClass)#421 (4) {
["name"]=>
string(4) "Blah3"
["full_name"]=>
string(11) "Blah3"
["id"]=>
string(32) "BlahBlah3"
["parent_id"]=>
string(32) "BlahBlahBlah3"
}
}
I want to filter to just the object that I want so what I did was
$found_label = array_filter($labels, function($obj) use($label) {
return $obj->name === $label;
});
But then the results I got is this
array(1) {
[1]=>
object(stdClass)#422 (4) {
["name"]=>
string(8) "Blah1"
["full_name"]=>
string(9) "Blah1"
["id"]=>
string(32) "BlahBlah2"
["parent_id"]=>
NULL
}
}
But what I really want is just this
object(stdClass)#422 (4) {
["name"]=>
string(8) "Blah1"
["full_name"]=>
string(9) "Blah1"
["id"]=>
string(32) "BlahBlah2"
["parent_id"]=>
NULL
}
Then I have to do this to just get the actual object
$theKey = key($found_label);
return $found_label[$theKey];
I thought they should be a better way of doing this, also I'm new to PHP.
You can't do that with array_filter, there is no way to stop it and return only the first result. If you can't use the key to extract the result you want from the array returned from array_filter, you should use a loop. Something like this:
$label = "wantedLabel";
foreach ($labels as $l) {
if( $l->name === $label ) {
print_r ($l);
break;
}
}
This:
<?php
$labels = array(
"0" => (object) array('name' => "name1", "title" => "title1"),
"1" => (object) array('name' => "name2", "title" => "title2")
);
$label = "name1";
$found_label = array_filter($labels, function($obj) use($label) {
return $obj->name === $label;
});
print_r($found_label[0]);
Produces:
stdClass Object ( [name] => name1 [title] => title1 )

Is there a function to combine these arrays in php?

Given arrays 'a1' and 'b1' how may they be combined them to produce the final array? Basically replacing the value within 'a1' with the array data for the matching value within 'b1'. I guess the question would be if there is a function that can do this that I'm not seeing.
$a1 = array('id1'=>array('a'=>'444-444',
'b'=>'222-222',
'c'=>'111-111'),
'id2'=>array('a'=>'888-888',
'b'=>'666-666',
'c'=>'555-555')
);
$b1 = array('222-222'=>array('first'=>array('9999',
'dddd',
'yyyy'),
'second'=>'mmgghh'
),
'666-666'=>array('first'=>array('bbbb',
'cccc',
'7777'),
'second'=>'ffffgggg'
)
);
Desired combination:
array(2) {
["id1"]=>
array(3) {
["a"]=>
string(7) "444-444"
["b"]=>
array(1) {
["222-222"]=>
array(2) {
["first"]=>
array(3) {
[0]=>
string(4) "9999"
[1]=>
string(4) "dddd"
[2]=>
string(4) "yyyy"
}
["second"]=>
string(6) "mmgghh"
}
}
["c"]=>
string(7) "111-111"
}
["id2"]=>
array(3) {
["a"]=>
string(7) "888-888"
["b"]=>
array(1) {
["666-666"]=>
array(2) {
["first"]=>
array(3) {
[0]=>
string(4) "bbbb"
[1]=>
string(4) "cccc"
[2]=>
string(4) "7777"
}
["second"]=>
string(6) "ffffgggg"
}
}
["c"]=>
string(7) "555-555"
}
}
array_walk_recursive($a1,function(&$value,$key,$addin){
if(is_scalar($value) && isset($addin[$value])){
$value = array($value=>$addin[$value]);
}
},$b1);

Categories