Sort an Array by values based on another Array - php

How do I turn this:
Array
(
[0] => stdClass Object
(
[id] => 123
[name] => Board
)
[1] => stdClass Object
(
[id] => 133
[name] => Staff
)
)
Into:
Array
(
[0] => stdClass Object
(
  [id] => 133
[name] => Staff
)
[1] => stdClass Object
(
[id] => 123
[name] => Board
)
)
Based on this:
Array( 'Staff', 'Board' )
In other words -- order an array of objects based on an array of values...

$ordering = ['Staff', 'Board'];
usort($myObjects, function($a, $b) use ($ordering) {
$idx1 = array_search($a->name, $ordering);
$idx2 = array_search($b->name, $ordering);
if($idx1 == $idx2)
return 0;
elseif($idx1 < $idx2)
return -1;
return 1;
});
This example does assume that $ordering will contain all names it's going to encounter. If not you'll have to patch behaviour in there (can't do that because I don't know 'where' you want the unmatched items to sort to).

Related

How to merge three arrays according to common key in php

I have three arrays first array include ids and employees name and second array have monthly collection with employee ids and third array have daily collection with employee id and daily collection I want to merge these array with ids and name and dcollection and monthly collection but the desired output is not coming here my first array $ids is
Array
(
[0] => stdClass Object
(
[id] => 1
[name] => Rohit
)
[1] => stdClass Object
(
[id] => 2
[name] => Emop1
)
[2] => stdClass Object
(
[id] => 3
[name] => Pankaj
)
[3] => stdClass Object
(
[id] => 4
[name] => tejpal singh
)
)
second array $q1 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[mcollecton] => 100
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[mcollecton] => 1222
)
)
third array $q2 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[dcollecton] => 300
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[dcollecton] => 150
)
)
so far what I have tried
$new_array = array();
foreach($ids as $k) {
$q1n = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1) {
if($k->id==$k1->id){
$mc = array("mc"=>$k1->mcollecton);
array_merge($q1n,$mc);
}
}
foreach($q2 as $k1){
if($k->id==$k1->id){
$dc = array("dc"=>$k1->dcollecton);
array_merge($q1n,$dc);
}
}
$a = array_merge($q1n,$mc);
$av = array_merge($q1n,$dc);
array_push($new_array,$q1n);
}
but the output is coming as
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
)
[1] => Array
(
[id] => 2
[name] => Emop1
)
[2] => Array
(
[id] => 3
[name] => Pankaj
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
)
)
I want the output be like
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
[mcollection] => 100
[dcollection] => 300
)
[1] => Array
(
[id] => 2
[name] => Emop1
[mcollection] => 1222
[dcollection] => 150
)
[2] => Array
(
[id] => 3
[name] => Pankaj
[mcollection] => 0
[dcollection] => 0
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
[mcollection] => 0
[dcollection] => 0
)
)
So I have tried many times but the desired output is not coming . please help me out how to get the desired output.
It seemed like that answer could be modified, or put in a function that you could call multiple times if needed to combine more than two arrays.
There's probably cleaner ways to handle this with array functions like array_merge or array_walk, but this is the general idea of how I might approach it. I haven't tested this, but maybe it's useful.
foreach($first as $key1 => $value){
foreach($second as $key2 => $value2){
// match the ids and check if array key exists on first array
if($value['id'] === $value2['id'] && empty($first[$key2])){
$first[$key][$key2] = $value2;
}
}
}
EDIT: Based on the answer you posted vs the question you asked, are you incrementing the collection numbers or just setting them? In other words why use +=? You should also be able to remove array_merge and array_push.
Below is geared more towards what you're trying to do. I haven't tested this either, but if you run into errors, post your code with the errors returned so that it's easier to debug:
foreach($ids as $k)
{
$thisArray = $newArray[] = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1)
{
if($k->id == $k1->id && !empty($k1->mcollecton))
{
$thisArray['mc'] = $k1->mcollecton;
}
}
foreach($q2 as $k2)
{
if($k->id == $k2->id && !empty($k2->dcollecton))
{
$thisArray['dc'] = $k2->dcollecton;
}
}
}
// This should have both new collections fields on all array items
print_r($newArray)

json array sort by value in php

I have JSON arrays of objects. I am trying to sort an array using usort. I want to use value field from field_listing_order. It sorted using value. I am missing something but not able to figure it out. please review the code. Thanks!
stdClass Object
(
[node_title] => abc
[nid] => 2281
[field_api_order_value] => 201
[field_node_entity_type] => node
[_data] => Array
(
[nid] => Array
(
[entity_type] => node
[entity] => stdClass Object
(
[title] => abc
[field_listing_order] => Array
(
[und] => Array
(
[0] => Array
(
[value] => 8
[format] =>
[safe_value] => 8
)
)
)
)
)
)
)
stdClass Object
(
[node_title] => abc
[nid] => 2243
[field_api_order_value] => 204
[field_node_entity_type] => node
[_data] => Array
(
[nid] => Array
(
[entity_type] => node
[entity] => stdClass Object
(
[title] => abc
[field_listing_order] => Array
(
[und] => Array
(
[0] => Array
(
[value] => 3
[format] =>
[safe_value] => 3
)
)
)
)
)
)
) stdClass Object
(
[node_title] => abc
[nid] => 2431
[field_api_order_value] => 242
[field_node_entity_type] => node
[_data] => Array
(
[nid] => Array
(
[entity_type] => node
[entity] => stdClass Object
(
[title] => abc
[field_listing_order] => Array
(
[und] => Array
(
[0] => Array
(
[value] => 1
[format] =>
[safe_value] => 1
)
)
)
)
)
)
)
and So on ...
foreach ($view->result as $result) {
$node = $result->_data['nid']['entity'];
$listing_order = $node->field_listing_order[LANGUAGE_NONE][0];
.....
// code goes here and it works well. sorting issue
}
usort ($node->field_listing_order[LANGUAGE_NONE][0], function($a, $b){
return strcmp($a->value, $b->value);
}); ?>
If you need to sort all the nodes using the field_listing_order value, you need to compare the values along the full path, from the first object to the value:
usort($view->result, function($a, $b) {
$la = $a->_data['nid']['entity']->field_listing_order[LANGUAGE_NONE][0]['value'];
$lb = $b->_data['nid']['entity']->field_listing_order[LANGUAGE_NONE][0]['value'];
return $la - $lb ;
});
In this case $a and $b are two different nodes which could be compared. That why you should compare the field_listing_order's value of these nodes. The answer is working with $la- $lb

PHP Sorting Multidimensional Associative Array by Key and Value

I'm trying to sort the following data by the date in the key and the value of Name.
The aim is to a get nice date ordered array with all the Names from the inner array in alphabetical order.
Array
(
[2017-07-27] => Array
(
[0] => stdClass Object
(
[Job] => stdClass Object
(
[Name] => Orange
)
)
[4] => stdClass Object
(
[Job] => stdClass Object
(
[Name] => Apple
)
)
)
[2017-07-22] => Array
(
[6] => stdClass Object
(
[Job] => stdClass Object
(
[Name] => Apple
)
)
[7] => stdClass Object
(
[Job] => stdClass Object
(
[Name] => Orange
)
)
)
[2017-07-29] => Array
(
[9] => stdClass Object
(
[Job] => stdClass Object
(
[Name] => Orange
)
)
[11] => stdClass Object
(
[Job] => stdClass Object
(
[Name] => Plumb
)
)
)
)
I'm pretty sure I should be using array_multisort but can't quite get the desired results.
You must split the code if you want to order on object properties, use the usort function.
Where $arr is your array:
uksort($arr, 'dateCmp');
foreach($arr as &$sub){
usort($sub, 'propCmp');
}
function dateCmp($a, $b){
return (strtotime($a) < strtotime($b) ? -1 : 1);
}
function propCmp($a, $b){
return ($a->Job->Name < $b->Job->Name ? -1 : 1);
}
Please try below code,
$sorted_vals = array();
ksort($multiArrs);
foreach($multiArrs as $key => $value) { // $multiArrs = your data array
$columns = null;
foreach ($value as $index => $element) {
$columns[] = $element->Job;
}
$temp = $value;
array_multisort($columns, SORT_ASC, $temp);
$sorted_vals[$key] = $temp;
}

PHP Multidimensional sort?

I have a rather annoying array structure to work with and I need to sort it by any arbitrary key combination. 2 records are displayed below but multiple records with or without the same structure will be present when sorting is actioned.
Here are two records.
Array(
[0] => Array
(
[cid] => 1
[title] => Mr
[first_name] => Abet
[last_name] => Simbad
[emails] => Array
(
[374] => Array
(
[eid] => 374
[name] => ski lodge
[email] => simbad#skifree.com
)
[373] => Array
(
[eid] => 373
[name] => work
[email] => simbad#work.com
)
[375] => Array
(
[eid] => 375
[name] => personal
[email] => simbad#gmail.com
)
)
)
[1] => Array
(
[cid] => 2
[title] => Mrs
[first_name] => Angie
[last_name] => Stokes
[emails] => Array
(
[590] => Array
(
[eid] => 590
[name] => work
[email] => angie#gmail.com
)
)
)
So if I wanted to sort by email in ascending order in the emails array, how can I get the second complete record to come first in the result array? angie#gmail.com comes before simbad#....
Also Some records will not contain an emails array. They would be last in the result set.
Any help would be much appreciated.
The array shown is a cut down version but I have addresses, notes, phones and websites in the same annoying structure. Ideally I could sort with something like
$sort = array('emails','email')
$data = sort_data_func('ASC',$sort,$data);
But anything steps in the right direction will help. :)
Here's some code I have so far
$sort = array('emails','email');
foreach($contacts as $ckey => $c){
if(is_array($c[$sort[0]])){
foreach($c[$sort[0]] as $key1 => $sort0){
if($sort0[$sort[1]]!=''){
$res[$sort[0]][$ckey][$sort[1]][] = $sort0[$sort[1]];
}
}
}
}
print_r($res);
Which produces:
Array
(
[emails] => Array
(
[0] => Array
(
[0] => simbad#skifree.com
[1] => simbad#work.com
[2] => simbad#gmail.com
)
[1] => Array
(
[0] => angie#gmail.com
)
)
)
But I have no idea where to go from here.
EDIT
OK I have the records in the currect order now but how can I keep the initial record ID in the resulting array?
Here's what I'm using.
$direction=='ASC'
function cmp_asc($a, $b){
$key = current(array_keys($a));
sort($a[$key]);
$a[$key] = current($a[$key]);
sort($b[$key]);
$b[$key] = current($b[$key]);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
function cmp_desc($a, $b){
$key = current(array_keys($a));
asort($a[$key]);
$a[$key] = current($a[$key]);
asort($b[$key]);
$b[$key] = current($b[$key]);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
if($direction=='ASC'){
usort($res[$sort[0]], 'cmp_asc');
}else{
usort($res[$sort[0]], 'cmp_desc');
}
In
Array
(
[emails] => Array
(
[0] => Array
(
[email] => Array
(
[0] => simbad#skifree.com
[1] => simbad#work.com
[2] => simbad#gmail.com
)
)
[1] => Array
(
[email] => Array
(
[0] => angie#gmail.com
)
)
)
)
Out
Array
(
[emails] => Array
(
[0] => Array
(
[email] => Array
(
[0] => angie#gmnail.com
)
)
[1] => Array
(
[email] => Array
(
[0] => simbad#skifree.com
[1] => simbad#work.com
[2] => simbad#gmail.com
)
)
)
)
One of the usort functions, combined with a self-written comparison function that detects the order in which two elements should be sorted, should do the trick.

What is an efficient way to split a multidimensional array into a set of arrays based on a value?

I have a multidimensional array like the following:
Array (
[0] => stdClass Object (
[name] => StackOverflow
[image] => CanHelp.jpg
)
[1] => stdClass Object (
[name] => AnotherObject
[image] => SecondImage.jpg
)
)
How can I arrange/split this array into groups based on the first letter of [name]?
i.e. There are about 1,000 items in this array, which I have already ordered alphabetically by [name], however I want to be able to have groups that begin with 'A', 'B', etc.
Like this, for 'A' and 'S':
Array (
[0] => stdClass Object (
[name] => AnotherObject
[image] => SecondImage.jpg
)
[1] => stdClass Object (
[name] => AndAnother
[image] => notImportant.jpg
)
)
Array (
[0] => stdClass Object (
[name] => StackOverflow
[image] => CanHelp.jpg
)
)
$split = array();
foreach ($array as $item) {
$split[$item->name[0]][] = $item;
}

Categories