This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 6 years ago.
One of my function return this array... Yes I have seen other examples here on SO but non where able to solve my problem.
array (size=4)
0 =>
array (size=2)
'refferrer' => string 'http://google.com/' (length=18)
'number_of_reffers' => string '15' (length=2)
1 =>
array (size=2)
'refferrer' => string 'https://facebook.com/' (length=21)
'number_of_reffers' => string '22' (length=2)
2 =>
array (size=2)
'refferrer' => string 'none' (length=4)
'number_of_reffers' => string '74' (length=2)
3 =>
array (size=2)
'refferrer' => string 'http://findy.com/' (length=17)
'number_of_reffers' => string '6' (length=1)
I will like to know how to sort this array in descending and asscending order using the
'number_of_reffers'...
What I am trying to say is that i want the one with the hishest number_of_reffers to come first, follow by the next and so on.
Is this possible and how can i do this in php.
Thanks for you help.
You need usort
Given your array, you would then do this:
usort( $array, 'sort_by_referrer_count' );
var_dump($array);
// This will sort ascending
function sort_by_referrer_count( $a, $b ) {
// Some defensive coding to ensure keys exist
$a = ( isset( $a['number_of_referrers'] ) ) ? $a['number_of_referrers'] : 0;
$b = ( isset( $b['number_of_referrers'] ) ) ? $b['number_of_referrers'] : 0;
if ($a == $b) {
return 0;
}
return ( $a < $b ) ? -1 : 1;
}
If you want descending, then you could do this (using the same function above):
usort( $array, 'sort_by_referrer_count' );
$array = array_reverse( $array );
In the most simplest sense; you may just want to try this:
<?php
// SORTING ALGORITHM:
// TO SORT IN THE OPPOSITE SENSE...
// (IE. ASCENDING [AS OPPOSED TO THE DEFAULT: DESCENDING]
// CHANGE THE LESS THAN (<) BELOW TO GREATER THAN (>)
function orderByNumRef($arrPrev, $arrNext) {
if ($arrPrev['number_of_reffers'] == $arrNext['number_of_reffers']) {
return 0;
}
return ($arrPrev['number_of_reffers'] < $arrNext['number_of_reffers']) ? -1 : 1;
}
//GIVEN ARRAY - DYNAMIC OR HARD-CODED
$arr = array(
array(
'refferrer' => 'http://google.com/',
'number_of_reffers' =>'15',
),
array(
'refferrer' => 'https://facebook.com/',
'number_of_reffers' =>'74',
),
array(
'refferrer' => 'http://findy.com/',
'number_of_reffers' =>'6',
),
);
//BEFORE SORTING:
var_dump($arr);
uasort($arr, 'orderByNumRef');
//AFTER SORTING:
var_dump($arr);
Hope it helps...
Try this:
<?php
$my_array;
//Sort Acceding
usort($my_array, create_function('$a,$b', 'return (Int)$a["number_of_reffers"]-(Int)$b["number_of_reffers"];'));
//Or sort Descending
usort($my_array, create_function('$a,$b', 'return (Int)$b["number_of_reffers"]-(Int)$a["number_of_reffers"];'));
The easiest way I find to do it is by creating a new array with the number_of_reffers as the key. Then sort the new array with either ksort() or krsort(). This in the end leaves the original array intact. Otherwise creating the original array in the intended format would be better.
<?php
// original array
$array = array(
array('refferrer' => 'http://google.com/', 'number_of_reffers' => '15'),
array('refferrer' => 'https://facebook.com/', 'number_of_reffers' => '22'),
array('refferrer' => 'none', 'number_of_reffers' => '74'),
array('refferrer' => 'http://findy.com/', 'number_of_reffers' => '6')
);
$foo = array(); // new empty array
// loop through $array, assign the number_of_reffers as the key for the refferrer
foreach ($array as $key => $bar) {
$foo[$bar['number_of_reffers']] = $bar['refferrer'];
}
/*
new array will be:
array(
'15' => 'http://google.com/',
'22' => 'https://facebook.com/'
etc .....
)
*/
// use Ksort / Krsort to sort the key asc or desc
ksort($foo); // ascending order
#krsort($foo); // descending order
die('<pre>'.print_r($foo, true).'</pre>'); // pretty printing of sorted array
?>
As a function ....
<?php
Function Referrer_sort($array, $asc = true) {
IF (!is_array($array)) { return 'not an array'; }
$result = array();
foreach ($array as $key => $value) {
$result[$value['number_of_reffers']] = $value['refferrer'];
}
switch ($asc) {
case false: krsort($result); return $result;
default: ksort($result); return $result;
}
}
$foo_asc = Referrer_sort($array);
$foo_desc = Referrer_sort($array, false);
die('<pre>Ascending:<br>'.print_r($foo_asc, true).'<br>Descending:<br>'.print_r($foo_desc, true).'</pre>');
?>
Changing the original array
Modifying the original array by changing the index key with the value of number_of_reffers.
<?php
Function Rebuild_Referrer_sort($array, $asc = true) {
IF (!is_array($array)) { return 'not an array'; }
$result = array();
foreach ($array as $key => $value) {
$result[$value['number_of_reffers']] = array('refferrer' => $value['refferrer'], 'number_of_reffers' => $value['number_of_reffers']);
}
switch ($asc) {
case false: krsort($result); return $result;
default: ksort($result); return $result;
}
}
$foo_asc = Rebuild_Referrer_sort($array);
$foo_desc = Rebuild_Referrer_sort($array, false);
die('<pre>Ascending:<br>'.print_r($foo_asc, true).'<br>Descending:<br>'.print_r($foo_desc, true).'</pre>');
/**
Returns:
Ascending:
Array
(
[6] => Array
(
[refferrer] => http://findy.com/
[number_of_reffers] => 6
)
[15] => Array
(
[refferrer] => http://google.com/
[number_of_reffers] => 15
)
[22] => Array
(
[refferrer] => https://facebook.com/
[number_of_reffers] => 22
)
[74] => Array
(
[refferrer] => none
[number_of_reffers] => 74
)
)
Descending:
Array
(
[74] => Array
(
[refferrer] => none
[number_of_reffers] => 74
)
[22] => Array
(
[refferrer] => https://facebook.com/
[number_of_reffers] => 22
)
[15] => Array
(
[refferrer] => http://google.com/
[number_of_reffers] => 15
)
[6] => Array
(
[refferrer] => http://findy.com/
[number_of_reffers] => 6
)
)
*/
?>
Related
I have the following two stdClass array from a loop. Now I need to merge them when when the key 'id' matches.
array (size=1)
0 =>
object(stdClass)[28]
public 'id' => string '78' (length=2)
public 'quantity' => string '5' (length=1)
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '1' (length=1)
So the final array become
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '6' (length=1)
Any help on how to do that ? I decode the original data using json_decode from [{"id":"78","quantity":"1"}] this format of data.
If you add an extra parameter to the json_decode, you can get the data as an associative array, which is much easier to work with. I've done a couple of versions ( the first is PHP 7 ), pick one which works with your system.
<?php
error_reporting ( E_ALL );
ini_set ( 'display_errors', 1 );
$arr1 = json_decode('[{"id":"78","quantity":"1"}, {"id":"79","quantity":"3"}]', true);
$arr2 = json_decode('[{"id":"78","quantity":"5"}]', true);
$arr3 = array_merge($arr1, $arr2);
// V7
$result = [];
foreach ( $arr3 as $element ) {
$result[$element['id']] = ($result[$element['id']]??0)
+ $element['quantity'];
}
print_r($result);
// Prior to V7
$result = array();
foreach ( $arr3 as $element ) {
if ( !isset($result[$element['id']]) ){
$result[$element['id']] = 0;
}
$result[$element['id']] += $element['quantity'];
}
print_r($result);
I've added another element to show how this adds up, but the output of this is...
Array
(
[78] => 6
[79] => 3
)
Array
(
[78] => 6
[79] => 3
)
Here is a solution that maintains the format in your original question.
It also uses array_reduce which is a concise way to process an array.
<?php
$input1 = '[{"id":"78","quantity":"7800"},
{"id":"79","quantity":"7900"},
{"id":"80","quantity":"8000"}]';
$input2 = '[{"id":"78","quantity":"6"},
{"id":"79","quantity":"8"},
{"id":"80","quantity":"6"},
{"id":"81","quantity":"7"}]';
$input1Arr = json_decode($input1);
$input2Arr = json_decode($input2);
$combinedArrays = array_merge($input1Arr, $input2Arr);
echo "combinedArrays = " . print_r($combinedArrays, true) . "\n";
$result = array_reduce($combinedArrays,
function($intermediateResult, $item){
if ( ! array_key_exists($item->id, $intermediateResult) ) {
// First time encountering an object with this id
$intermediateResult[$item->id] = $item;
}
else {
// We have an object with this id already so just add the quantity
$intermediateResult[$item->id]->quantity += $item->quantity;
}
return $intermediateResult;
}, []);
// Get the values from the result array
print_r(array_values($result));
this one is a little Q&A-style...
i've been searching for this situation and couldn't find any solution, so i build my own.
it took me a few days to get a working code for my needs, but now i am wondering if there's a more efficient way:
$data = [
['a','aa','aaa'],
['a','aa','aab'],
['a','aa','aac'],
['a','ab'],
['a','ac','aca'],
['b','ba'],
['b','bb'],
['b','bc'],
];
function tree($values){
$on_end = sizeof($values) == 1 && sizeof($values[0]) == 0;
if ( $on_end ) return null;
$tree1 = [];
$tree2 = [];
foreach ($values as $a){
$parent = $a[0];
//remove the first column
array_shift($a);
$tree1[ $parent ][] = $a;
}
foreach ($tree1 as $parent => $b){
$tree2[ $parent ] = tree( $b );
}
return $tree2;
}
echo "<pre>".print_r(tree($data),true)."</pre>";
this is the result:
Array
(
[a] => Array
(
[aa] => Array
(
[aaa] =>
[aab] =>
[aac] =>
)
[ab] =>
[ac] => Array
(
[aca] =>
)
)
[b] => Array
(
[ba] =>
[bb] =>
[bc] =>
)
)
if anybody got a better one, please post it!
You have a shortest solution ... but it's using eval function erk
<?php
$data = [
['a','aa','aaa'],
['a','aa','aab'],
['a','aa','aac'],
['a','ab'],
['a','ac','aca'],
['b','ba'],
['b','bb'],
['b','bc'],
];
function arrayToTree_eval(array $source, $defaultValue = null) {
$tree = [];
foreach( $source as $values ) {
eval(sprintf('$tree%s = $defaultValue;', '["' . implode('"]["', $values) . '"]'));
}
return $tree;
}
var_dump( arrayToTree_eval($data) );
7 lines of code, and hop !
array (size=2)
'a' =>
array (size=3)
'aa' =>
array (size=3)
'aaa' => null
'aab' => null
'aac' => null
'ab' => null
'ac' =>
array (size=1)
'aca' => null
'b' =>
array (size=3)
'ba' => null
'bb' => null
'bc' => null
:)
I have a php array like this
print_r(myarray) is
Array ( [0] => Array ( [#xsi:nil] => true ) [1] => Array ( [#xsi:nil] => true ) [2] => Array ( [#xsi:nil] => true ) [3] => 'some value' [4] => Array ( [#xsi:nil] => true ))
I need to eliminate the values Array ( [#xsi:nil] => true ) or just to replace them with say "nill". I tried a lot, this being a nested array i couldnt get the key for the values [#xsi:nil] => true
How to check in php for the indexes which hold the value Array ( [#xsi:nil] => true )? and replace them with say 'nill'?
trial one :
$key1 = array_search(array('#xsi:nil'=>'true'), array_column($arrays, 'NOTE')); //to catch the indexes.
function searchMyCoolArray($arrays, $key, $search) {
$count = 0;
foreach($arrays as $object) {
if(is_object($object)) {
$ob1 = $object;
$object = get_object_vars($object);
$key1 = array_search(40489, array_column($arrays, 'uid'));
}
if(array_key_exists($key, $object) && $object[$key] == $search)
{
// print_r($first_names_note[$key]);
// echo "ffgfg ".$ob1[0]." rtrtrt";
// var_dump($object);
// print_r($arrays[$key]);
// echo $object;
// print_r($object);
// print_r($first_names_note)."<br>";
$count++;
//echo "sddsdsdsd";
}
}
return $count;
}
echo searchMyCoolArray($first_names_note, '#xsi:nil', 'true');
here i got the count correct, but it was not i need, I tried to get the indexs in the function itself, but failed
Please help, i googled alot pleeeeeeeeeeeeeeeeez
You may try to use array_walk to traverse the array and then unset all elements with the key #xsi:nil like this:
<?php
$arr = array(
array("#xsi:nil" => true),
array("#xsi:nil" => true),
array("#xsi:nil" => true),
array("some_value" =>4),
array("#xsi:nil" => true),
);
array_walk($arr, function(&$data){
if(is_array($data) && array_key_exists("#xsi:nil", $data)){
unset($data["#xsi:nil"]);
$data[] = "nil";
}
});
var_dump($arr);
// IF YOU WANT TO REMOVE ALL EMPTY ARRAYS COMPLETELY, JUST DO THIS:
$arr = array_filter($arr);
var_dump($arr);
// GET THE LENGTH OF THE FILTERED ARRAY.
$count = count($arr);
echo $count; //<== PRODUCES 5
// THE 1ST VAR_DUMP() PRODUCES:
array (size=5)
0 =>
array (size=1)
0 => string 'nil' (length=3)
1 =>
array (size=1)
0 => string 'nil' (length=3)
2 =>
array (size=1)
0 => string 'nil' (length=3)
3 =>
array (size=1)
'some_value' => int 4
4 =>
array (size=1)
0 => string 'nil' (length=3)
// THE 2ND VAR_DUMP() PRODUCES:
array (size=5)
0 =>
array (size=1)
0 => string 'nil' (length=3)
1 =>
array (size=1)
0 => string 'nil' (length=3)
2 =>
array (size=1)
0 => string 'nil' (length=3)
3 =>
array (size=1)
'some_value' => int 4
4 =>
array (size=1)
0 => string 'nil' (length=3)
Test it out HERE.
Cheers & Good Luck...
This is not the answer, the code for the answer was provided by #Poiz
Here is my complete code which i formatted
//my array
$arr = Array (Array ( '#xsi:nil' => 'true' ), Array ('#xsi:nil' => 'true' ), Array ( '#xsi:nil' => 'true' ) );
// print_r($arr);
//performed array walk
array_walk($arr, function(&$data){
if(is_array($data) && array_key_exists("#xsi:nil", $data)){
unset($data["#xsi:nil"]);
$data = "nil";
}
});
print_r($arr);
//OUTPUT : Array ( [0] => nil [1] => nil [2] => nil )
This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 3 months ago.
Array
(
[0] => Array
(
[file] => /var/websites/example.com/assets/images/200px/1419050406e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
[md5] => 42479bee7a304d2318250de2ef1962a9
[url] => http://example.com/assets/images/200px/1419050406e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
)
[1] => Array
(
[file] => /var/websites/example.com/assets/images/200px/21277792606e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
[md5] => 42479bee7a304d2318250de2ef1962a9
[url] => http://example.com/assets/images/200px/21277792606e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
)
)
How can I remove md5 key duplicates from above array?
<?php
$data = array(
array(
'md5' => 'alpha',
'some' => 'value',
),
array(
'md5' => 'alpha',
'some' => 'other value',
),
array(
'md5' => 'bravo',
'some' => 'third value',
),
);
// walk input array
$_data = array();
foreach ($data as $v) {
if (isset($_data[$v['md5']])) {
// found duplicate
continue;
}
// remember unique item
$_data[$v['md5']] = $v;
}
// if you need a zero-based array, otheriwse work with $_data
$data = array_values($_data);
PHP does already have a function to remove duplicate elements from an array. But unfortunately, array_unique does only support string based comparisons:
Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same. The first element will be used.
The problem is that any array turned into a string is equal to any other array:
Arrays are always converted to the string "Array"; […]
But you can use the uniqueness of array keys to solve this:
$index = array();
foreach ($arr as $key => $item) {
if (isset($index[$item['md5']])) {
unset($item[$key]);
}
$index[$item['md5']] = TRUE;
}
Here is my final function after your help guys.... Hope it helps somebody in the future...
$data = array(
array(
'md5' => 'alpha',
'some' => 'value',
),
array(
'md5' => 'alpha',
'some' => 'other value',
),
array(
'md5' => 'bravo',
'some' => 'third value',
),
);
// walk input array
function remove_duplicateKeys($key,$data){
$_data = array();
foreach ($data as $v) {
if (isset($_data[$v[$key]])) {
// found duplicate
continue;
}
// remember unique item
$_data[$v[$key]] = $v;
}
// if you need a zero-based array
// otherwise work with $_data
$data = array_values($_data);
return $data;
}
$my_array = remove_duplicateKeys("md5",$data);
As array_unique operates on flat arrays, you can not use it directly. But you can first map all 'md5' values to a flat array, unique it and then get the elements with array_intersect_key:
$allMd5s = array_map(function($v) {return $v['md5'];}, $array);
$uniqueMd5s = array_unique($md5);
$result = array_intersect_key($arr, $uniqueMd5s);
Use array_filter(). Quick code test (doesn't necessarily mirror your situation, but you should get the idea):
<?php
header('Content-Type: Text/Plain');
$array = array(
0 => array('name' => 'samson'),
1 => array('name' => 'delilah'),
2 => array('name' => 'samson'),
3 => array('name' => 'goliath'),
);
$md5Processed = array();
$newArray = array_filter($array, "uniqueMD5");
print_r($newArray);
exit;
function uniqueMD5( $data ){
global $md5Processed;
if( !in_array( $data['name'], $md5Processed ) )
{
$md5Processed[] = $data['name'];
return true;
}
}
// your array
$array = array(...);
// will be used to store md5 hashes
$md5 = array();
// walk through array
foreach ($array as $key => $arr) {
// have we already seen this md5 hash?
if (in_array($arr['md5'], $md5)){
// remove element
unset($array[$key]);
}else {
// keep element, but add it's md5
$md5[] = $arr['md5'];
}
}
Tldr.: The obligatory one-liner:
$out = array_values ( array_intersect_key( $in, array_unique( array_column( $in, 'md5' ) ) ) );
And step by step (with my own example):
$in = [
[ 'k' => 'a' ],
[ 'k' => 'a' ],
[ 'k' => 'b' ]
];
print_r( array_column( $in, 'k' ) );
array_column returns a flat array, only with the values from all 'k'-keys:
Array
(
[0] => a
[1] => a
[2] => b
)
We can now filter that with array_unique:
print_r( array_unique( array_column( $in, 'k' ) ) ) );
To get:
Array
(
[0] => a
[2] => b
)
See that we kept the keys of the original array (0 and 2)?
We can use that with array_intersect_key. It computes the intersection of arrays using keys for comparison.
print_r( array_intersect_key( $in, array_unique( array_column( $in, 'k' ) ) ) );
We get the first [0] and third [2] entry of our original array.
Array
(
[0] => Array
(
[k] => a
)
[2] => Array
(
[k] => b
)
)
Now the keys are messed up (which might lead to problems if for loops), so we wrap the whole thing in array_values:
print_r(
array_values( array_intersect_key( $in, array_unique( array_column( $in, 'k' ) ) ) )
);
Array
(
[0] => Array
(
[k] => a
)
[1] => Array
(
[k] => b
)
)
Take a look at the function array_unique.
This question already has answers here:
PHP Sort a multidimensional array by element containing Y-m-d H:i:s date
(11 answers)
Closed 11 months ago.
I have an array like the following:
Array
(
[0] => Array
(
'name' => "Friday"
'weight' => 6
)
[1] => Array
(
'name' => "Monday"
'weight' => 2
)
)
I would like to grab the last values in that array (the 'weight'), and use that to sort the main array elements. So, in this array, I'd want to sort it so the 'Monday' element appears before the 'Friday' element.
You can use usort as:
function cmp($a, $b) {
return $a['weight'] - $b['weight'];
}
usort($arr,"cmp");
Can be done using an anonymous function.
Also if your 'weight' is a string use one of the other returns (see the commented out lines):
<?php
$arr = array(
0 => array (
'name' => 'Friday',
'weight' => 6,
),
1 => array (
'name' => 'Monday',
'weight' => 2,
),
);
// sort by 'weight'
usort($arr, function($a, $b) { // anonymous function
// compare numbers only
return $a['weight'] - $b['weight'];
// compare numbers or strings
//return strcmp($a['weight'], $b['weight']);
// compare numbers or strings non-case-sensitive
//return strcmp(strtoupper($a['weight']), strtoupper($b['weight']));
});
var_export($arr);
/*
array (
0 => array (
'name' => 'Monday',
'weight' => 2,
),
1 => array (
'name' => 'Friday',
'weight' => 6,
),
)
*/
You can also use an anonymous function.
usort($items, function($a, $b) {
return $a['name'] > $b['name'];
});
Agree with usort, I also sometimes use array_multisort (http://ca2.php.net/manual/en/function.usort.php) example 3, sorting database results.
You could do something like:
<?php
$days = array(
array('name' => 'Friday', 'weight' => 6),
array('name' => 'Monday', 'weight' => 2),
);
$weight = array();
foreach($days as $k => $d) {
$weight[$k] = $d['weight'];
}
print_r($days);
array_multisort($weight, SORT_ASC, $days);
print_r($days);
?>
Output:
Array
(
[0] => Array
(
[name] => Friday
[weight] => 6
)
[1] => Array
(
[name] => Monday
[weight] => 2
)
)
Array
(
[0] => Array
(
[name] => Monday
[weight] => 2
)
[1] => Array
(
[name] => Friday
[weight] => 6
)
)
If the filed you sort by is string like title name,
array_multisort + Flags for Natural Sorting and CaseInSensitivity are the way to go:
$sort_by_title = array();
foreach($items as $item) {
$sort_by_title [] = $item['title'];
}
array_multisort($sort_by_title , SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $items );
NOTE, if the element you are sorting on is a float like .0534 and .0353 (like for a percentage), then you have to multiply both by 1000. not sure why frankly... it appears that usort seems to compare the integer values.
took me awhile to figure that one out...
and 2 tips that may not be immediately obvious:
if your arrays are objects, you can use return $a->weight - $b->weight of course
if you return $b->weight - $a->weight, it will sort desending.
Here's a cool function that might help:
function subval_sort($a,$subkey,$sort) {
foreach($a as $k=>$v) {
$b[$k] = strtolower($v[$subkey]);
}
if($b)
{
$sort($b);
foreach($b as $key=>$val) {
$c[] = $a[$key];
}
return $c;
}
}
Send in the array as $a the key as $subkey and 'asort' or 'sort' for the $sort variable