Sort array numeric before string? - php

I can't sort my array so that numbers comes before - (hyphen).
My array today:
Array
(
[-] => Test
[0] => Test
[1] => Test
[2] => Test
)
The order I want:
Array
(
[0] => Test
[1] => Test
[2] => Test
[-] => Test
)
I have searched both here and on Google. But found no answers. I have tried experimenting with ksort() and usort(), but without success.

You could create your own compare function with uksort which handels such special cases.
uksort($a, function($a, $b) {
if (is_numeric($a) && is_numeric($b)) return $a - $b;
else if (is_numeric($a)) return -1;
else if (is_numeric($b)) return 1;
return strcmp($a, $b);
});

Use natural order sorting function
natsort()
example:
$arr = ['_', 6, 3, 5];
natsort($arr);
print_r($arr);
output:
Array
(
[2] => 3
[3] => 5
[1] => 6
[0] => _
)
If you want to sort by keys then you can use ksort() function with flag SORT_NATURAL ksort($arr, SORT_NATURAL);
example:
$arr = [
'_' => 'test',
6 => 'test',
3 => 'test',
5 => 'test'
];
ksort($arr, SORT_NATURAL);

function check($x, $y){
if(is_numeric($x) && !is_numeric($y))
return 1;
else if(!is_numeric($x) && is_numeric($y))
return -1;
else
return ($x < $y) ? -1 : 1;
}
$array = array("-", "1", "2", "3");
usort ( $array , 'check' );

Related

Sort Multi dimensional array by Value and not include to sorting if priority value is 0

I have to sort below given array by Priority. If priority value is 0 then not include in sorting array. I have tried many ways but not getting output as expected.
Array
(
[recently_viewed] => Array
(
[priority] => 1
[no_of_products] => 1
)
[recently_visited_cat] => Array
(
[priority] => 1
[no_of_products] => 1
)
[last_ordered_items] => Array
(
[priority] => 3
[no_of_products] => 3
)
[searched_based] => Array
(
[priority] => 0
[no_of_products] => 4
)
[cart_based] => Array
(
[priority] => 1
[no_of_products] => 5
)
[wishlist_based] => Array
(
[priority] => 1
[no_of_products] => 6
)
[sku_based] => Array
(
[priority] => 0
[no_of_products] => 7
)
)
Please help me with this.
You can use array_filter() function to exclude records with 0 priority. After it you can sort the array with help uasort() function. For example:
$arr = array_filter($arr, function($element) {
return $element['priority'] > 0;
});
uasort($arr, function ($a, $b) {
if ($a['priority'] === $b['priority']) {
return 0;
}
return ($a['priority'] < $b['priority']) ? -1 : 1;
});
You can us array_filter (doc - for check bigger then 0) and then uasort (doc):
$arr = [];
$arr["recently_viewed"] = ["priority" => 1, "no_of_products" =>1];
$arr["searched_based"] = ["priority" => 0, "no_of_products" =>4];
$arr["last_ordered_items"] = ["priority" => 3, "no_of_products" =>3];
$arr = array_filter($arr, function ($e) {return $e["priority"];});
uasort($arr, function($a, $b) {
return $a['priority'] - $b['priority'];
});
Live example: 3v4l
You can use array_filter with callback function to remove the values with ZERO
$arr = array_filter($arr, function ($e) {return $e["priority"];});
This will remove all the sub-array which has priority values ZERO.
Now you can apply usort to sort the array
usort($arr, function($a, $b) {
return $a['priority'] <=> $b['priority'];
});
See Working Code Live

Sort Array in numerical order based on a numerical value within the element [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
How do you sort an array in numerical order, based on a numerical value within the element: where the element is a String?
for eg. from:
Array(
0 => One:3
1 => Two:1
2 => Three:4
3 => Four:2
)
to:
Array(
0 => Two:1
1 => Four:2
2 => One:3
3 => Three:4
)
Given your input array:
$arr = array('One:3','Two:1','Three:4','Four:2');
usort($arr, function($a, $b) {
return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT);
});
print_r($arr);
outputs:
Array
(
[0] => Two:1
[1] => Four:2
[2] => One:3
[3] => Three:4
)
If your string follow this pattern you can use the uasort() function and build a function that sorts it. Example:
$elements = array('One:3','Two:1','Three:4','Four:2');
uasort($elements, function($a, $b){
$a = array_pop(explode(':', $a));
$b = array_pop(explode(':', $b));
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
});
print_r($elements); // Array ( [1] => Two:1 [3] => Four:2 [0] => One:3 [2] => Three:4 )

How to get the difference of specific data types encoded into arrays

How to get the difference of arrays containing data-types?
First array:
Array
(
[0] => Array
(
[ID] => 21323154
[NAME] => Name_2
[PREVIEW_TEXT] => Text_2
)
)
Second array:
Array
(
[0] => Array
(
[ID] => 543547564
[NAME] => Name_1
[PREVIEW_TEXT] => Text_1
)
[1] => Array
(
[ID] => 222213322
[NAME] => Name_2
[PREVIEW_TEXT] => Text_2
)
[2] => Array
(
[ID] => 333876833
[NAME] => Name_3
[PREVIEW_TEXT] => Text_3
)
)
The result should be an array:
Array
(
[0] => Array
(
[ID] => 543547564
[NAME] => Name_1
[PREVIEW_TEXT] => Text_1
)
[1] => Array
(
[ID] => 333876833
[NAME] => Name_3
[PREVIEW_TEXT] => Text_3
)
)
I tried different options, but they all return the result found the difference, i.e. the first array.
I have a different ID
Just try with:
$output = array_udiff($arraySecond, $arrayFirst, function($a, $b){
return strcmp($a['NAME'], $b['NAME']);;
});
Output:
array(2) {
[0] =>
array(3) {
'ID' =>
int(543547564)
'NAME' =>
string(6) "Name_1"
'PREVIEW_TEXT' =>
string(6) "Text_1"
}
[2] =>
array(3) {
'ID' =>
int(333876833)
'NAME' =>
string(6) "Name_3"
'PREVIEW_TEXT' =>
string(6) "Text_3"
}
}
If both arrays are large, array_diff will be very inefficient, because it compares each element of the first array with each element of the second. A faster solution is to split the process into two steps: first, generate a set of keys to remove:
$remove = array();
foreach($firstArray as $item)
$remove[$item['name']] = 1;
and then iterate over the second array and add "good" items to the result:
$result = array();
foreach($secondArray as $item)
if(!isset($remove[$item['name']]))
$result []= $item;
This will give you linear performance, while array_diff is quadratic.
Diff both arrays against the field (column) you want to, give back only those entries then (thanks to keys):
$col = 'NAME';
$diff = array_intersect_key($b, array_diff(array_column($b, $col), array_column($a, $col)));
print_r($diff);
If you prefer to have this less quadratic but linear, you can also solve it via iteration (inspired by georg's answer but using array_column() again):
$filtered = function ($col, $a, $b) {
return iterator_to_array(call_user_func(function () use ($col, $a, $b) {
$coled = array_flip(array_column($a, $col));
foreach ($b as $bk => $bv) if (!isset($coled[$bv[$col]])) yield $bk => $bv;
}));
};
print_r($filtered('NAME', $a, $b));
With $a and $b as outlined, you will get the following result for both examples:
Array
(
[0] => Array
(
[ID] => 543547564
[NAME] => Name_1
[PREVIEW_TEXT] => Text_1
)
[2] => Array
(
[ID] => 333876833
[NAME] => Name_3
[PREVIEW_TEXT] => Text_3
)
)
// 1.) - diff against column, intersect keys
$filtered = function($col, $a, $b) {
return array_intersect_key($b, array_diff(array_column($b, $col), array_column($a, $col)));
};
// 2.) - iterate and take only unset by column
$filtered = function ($col, $a, $b) {
return iterator_to_array(call_user_func(function () use ($col, $a, $b) {
$coled = array_flip(array_column($a, $col));
foreach ($b as $bk => $bv) if (!isset($coled[$bv[$col]])) yield $bk => $bv;
}));
};
// 3.) - array_udiff against column
$filtered = function($col, $a, $b) {
return array_udiff($b, $a, function ($a, $b) use ($col) {
return strcmp($a[$col], $b[$col]);
});
};
Usage:
print_r($filtered('NAME', $a, $b));
Where $a is the array containing the elements to remove from the $b array. So $a is the first array of the question and $b is the second array of the question.

PHP sort multidimensional array by date

I'm having a problem. I have a multidimensional array, that looks like this:
Array ( [0] =>
Array (
[0] => Testguy2's post.
[1] => testguy2
[2] => 2013-04-03
)
[1] => Array (
[0] => Testguy's post.
[1] => testguy
[2] => 2013-04-07
)
);
I want to sort the posts from the newest date to the oldest date, so it looks like this:
Array ( [1] => Array (
[0] => Testguy's post.
[1] => testguy
[2] => 2013-04-07
)
[0] => Array (
[0] => Testguy2's post.
[1] => testguy2
[2] => 2013-04-03
)
);
How do I sort it?
function cmp($a, $b){
$a = strtotime($a[2]);
$b = strtotime($b[2]);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
usort($array, "cmp");
Or for >= PHP 7
usort($array, function($a, $b){
return strtotime($a[2]) <=> strtotime($b[2]);
});
You can do it using usort with a Closure :
usort($array, function($a, $b) {
$a = strtotime($a[2]);
$b = strtotime($b[2]);
return (($a == $b) ? (0) : (($a > $b) ? (1) : (-1)));
});
I'm just stepping away from my desk for the day so I can't offer specifics. But here's a good place to get started that includes examples: array_multisort
$dates = array();
foreach($a AS $val){
$dates[] = strtotime($val[2]);
}
array_multisort($dates, SORT_ASC, $a);

Find the difference from two arrays in php

--$arr1----
Array
(
[0] => Array
(
[id] => 1
[Name] => AAA
)
[1] => Array
(
[id] => 6
[Name] => BBB
)
)
--$arr2---
Array
(
[0] => Array
(
[id] => 1
[Name] => AAA
)
[1] => Array
(
[id] => 6
[Name] => BBB
)
[2] => Array
(
[id] => 46
[Name] => CCC
)
)
I would like the final result as following. Is there anyone can help me?
--Final Result--
Array
(
[0] => Array
(
[id] => 46
[Name] => CCC
)
)
UPDATE---
In this case, the result of array_diff($arr1,$arr2) is empty.
The easiest way is Mark Baker's solution or just write your own simple function:
Code:
function arrdiff($a1, $a2) {
$res = array();
foreach($a2 as $a) if (array_search($a, $a1) === false) $res[] = $a;
return $res;
}
print_r(arrdiff($arr1, $arr2));
Output:
Array
(
[0] => Array
(
[id] => 46
[name] => CCC
)
)
$arr1 = array(array('id' => 1, 'Name' => 'AAA'),
array('id' => 6, 'Name' => 'BBB')
);
$arr2 = array(array('id' => 1, 'Name' => 'AAA'),
array('id' => 6, 'Name' => 'BBB'),
array('id' => 46, 'Name' => 'CCC')
);
$results = array_diff(array_map('serialize',$arr2),array_map('serialize',$arr1));
$results = array_map('unserialize',$results);
var_dump($results);
EDIT
And just for the sheer fun of it, you could use array_filter() instead of array_diff() - which means no need to serialize anything at all
$results = array_filter($arr2, function ($value) use($arr1) { return !in_array($value,$arr1); } );
var_dump($results);
You should use array_diff():
$finalResult = array_diff($arr2, $arr1);
If you need more complex comparison you may also build foreach loop and use like this:
function compareItems( $a, $b){
return $a['id'] == $b['id']; // Example compare criteria
}
$result = array();
foreach( $arr1 as $item){
foreach( $arr2 as $key => $it){
if( !compareItems( $item, $it)){
$result[] = $it; // Either build new array
unset( $arr2[$key]); // Or remove items from original array
break;
}
}
}
And than you'll probably want to implement the same with reversed order of $arr1 and $arr2.
You can solve this with array_udiff()
function arr_comp($a, $b)
{
if ($a['id'] == $b['id'])
return 0;
else if ($a['id'] > $b['id'])
return 1;
else
return -1;
}
$result = array_udiff($arr2, $arr1, 'arr_comp');
or if you don't know in which array the differences may be you can try:
$res1 = array_udiff($arr1, $arr2, 'arr_comp');
$res2 = array_udiff($arr2, $arr1, 'arr_comp');
$result = array_merge($res1, $res2);
$arrDif=array();
$i=0;
foreach($arr1 as $value)
{
if(!in_array($value, $arr2))
{
$arrDif[$i]=$value;
$i++;
}
}
Take a look at the PHP built-in function array_diff. That'll help you out :-) Just pass your two arrays, and store the array returned by array_diff(), which will contain the differences between the two arrays.
As you're using multi-dimensional arrays, look at this comment on the PHP website: http://www.php.net/manual/en/function.array-diff.php#98680.

Categories