Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Используйте usort , вот пример, адаптированный из руководства:
function cmp($a, $b)
{
return strcmp($a->name, $b->name);
}
usort($your_data, "cmp");
редактирует импортированные из комментариев:
Если вы сортируете массив изнутри класса, и ваша функция сортировки cmp
также определена внутри класса, тогда используйте это:
usort($your_data, array($this, "cmp"))
Если все это не удается, это другое решение:
$names = array();
foreach ($my_array as $my_object) {
$names[] = $my_object->name; //any object field
}
array_multisort($names, SORT_ASC, $my_array);
return $my_array;
, если вы используете php oop, вам может потребоваться изменить:
public static function cmp($a, $b)
{
return strcmp($a->name, $b->name);
}
//in this case FUNCTION_NAME would be cmp
usort($your_data, array('YOUR_CLASS_NAME','FUNCTION_NAME'));
Если вам нужно отсортировать только одно поле, тогда usort
- хороший выбор. Однако решение быстро становится беспорядочным, если вам нужно сортировать по нескольким полям. В этом случае можно использовать библиотеку YaLinqo *, которая реализует синтаксис SQL-подобных запросов для массивов и объектов. Он имеет довольно синтаксис для всех случаев:
$sortedByName = from($objects)->orderBy('$v->name');
$sortedByCount = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');
Здесь '$v->count'
является сокращением для function ($v) { return $v->count; }
(либо можно использовать). Эти цепочки методов возвращают итераторы, но вы можете получить массивы, добавив ->toArray()
в конце, если вам это нужно.
*, разработанный мной
Простая альтернатива, позволяющая динамически определять поле, на котором основана сортировка:
$order_by = 'name';
usort($your_data, function ($a, $b) use ($order_by)
{
return strcmp($a->{$order_by}, $b->{$order_by});
});
Это основано на классе Closure , который позволяет анонимные функции , Он доступен с PHP 5.3.
Суть всех ответов здесь в том, что они используют имена статических полей, поэтому я написал скорректированную версию в стиле ООП. Предположим, вы используете методы getter, которые вы можете использовать непосредственно в этом классе и использовать имя поля в качестве параметра. Возможно, кто-то сочтет это полезным.
class CustomSort{
public $field = '';
public function cmp($a, $b)
{
/**
* field for order is in a class variable $field
* using getter function with naming convention getVariable() we set first letter to uppercase
* we use variable variable names - $a->{'varName'} would directly access a field
*/
return strcmp($a->{'get'.ucfirst($this->field)}(), $b->{'get'.ucfirst($this->field)}());
}
public function sortObjectArrayByField($array, $field)
{
$this->field = $field;
usort($array, array("Your\Namespace\CustomSort", "cmp"));;
return $array;
}
}
Если вы используете это внутри Codeigniter, вы можете использовать методы:
usort($jobs, array($this->job_model, "sortJobs")); // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.
@rmooney спасибо за предложение. Это действительно помогает мне.
Вы можете использовать эту функцию (работает в версии PHP> = 5.3):
function sortArrayByKey(&$array,$key,$string = false,$asc = true){
if($string){
usort($array,function ($a, $b) use(&$key,&$asc)
{
if($asc) return strcmp(strtolower($a{$key}), strtolower($b{$key}));
else return strcmp(strtolower($b{$key}), strtolower($a{$key}));
});
}else{
usort($array,function ($a, $b) use(&$key,&$asc)
{
if($a[$key] == $b{$key}){return 0;}
if($asc) return ($a{$key} < $b{$key}) ? -1 : 1;
else return ($a{$key} > $b{$key}) ? -1 : 1;
});
}
}
Пример:
sortArrayByKey($yourArray,"name",true); //String sort (ascending order)
sortArrayByKey($yourArray,"name",true,false); //String sort (descending order)
sortArrayByKey($yourArray,"id"); //number sort (ascending order)
sortArrayByKey($yourArray,"count",false,false); //number sort (descending order)
$a->{$key}
и $b->{$key}
, а не $a[$key]
и $b[$key]
, поскольку мы, строго говоря, имеем дело со свойствами, а не с элементами массива, но это был еще тот ответ, который я искал.
– SteJ
19 November 2016 в 16:19
Вы можете использовать usort
, например:
usort($array,function($first,$second){
return strcmp($first->name, $second->name);
});
Лучше использовать закрытие
usort($your_data, function($a, $b)
{
return strcmp($a->name, $b->name);
});
Обратите внимание, что это не в документации PHP, но если вы используете закрытие 5.3+, поддерживаются аргументы, доступные для вызова.
strcmp($b->name, $a->name)
– zxcat
19 March 2016 в 01:53
Если вам требуется локальное сопоставление строк, вы можете использовать strcoll
вместо strcmp
.
Воспользоваться первым использованием setlocale
с LC_COLLATE
, чтобы установить локальную информацию, если необходимо.
usort($your_data,function($a,$b){
setlocale (LC_COLLATE, 'pl_PL.UTF-8'); // Example of Polish language collation
return strcoll($a->name,$b->name);
});
usort($array, 'my_sort_function');
var_dump($array);
function my_sort_function($a, $b)
{
return $a->name < $b->name;
}
Тот же код будет с полем count
.
Подробнее о usort
: http://ru2.php.net/usort
Btw, откуда вы взяли этот массив? Надеюсь, что не из базы данных?
$result
будет содержать TRUE
, если он успешный, и ваше сравнение должно быть $a->name > $b->name
. :)
– cambraca
26 November 2010 в 04:56
ORDER BY count
– zerkms
26 November 2010 в 05:02
create_function('$a,$b', "return $a->count < $b->count;")
, но я не могу заставить его работать :( Я получаю несколько уведомлений и предупреждение, что usort ожидает, что параметр 2 будет действительным обратным вызовом
– Alex
26 November 2010 в 05:11
Вы можете использовать функцию отсортированную из Nspl :
use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;
// Sort by property value
$sortedByCount = sorted($objects, propertyGetter('count'));
// Or sort by result of method call
$sortedByName = sorted($objects, methodCaller('getName'));
Спасибо за вдохновение, мне также пришлось добавить внешний параметр $ переводчика
usort($listable_products, function($a, $b) {
global $translator;
return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});
, если вы хотите отсортировать даты
usort($threads,function($first,$second){
return strtotime($first->dateandtime) < strtotime($second->dateandtime);
});