- Как отсортировать массив в алфавитном порядке в PHP?
- Массив в алфавитном порядке PHP
- Второй способ выстроить массив в алфавитном порядке PHP
- Сортировка массива в php без использования sort(), работающая с русским текстом
- Php массив сортировка кириллицы
- Как отсортировать многоуровневый массив? - Регистронезависимая сортировка для кириллицы?
- Ответы (2 шт):
Как отсортировать массив в алфавитном порядке в PHP?
При работе на многих сайтах часто встречается вопрос сортировки данных массива в алфавитном порядке. Многие для этого пишут дополнительные массивы, сравнивают крупные таблицы и перебирают каждое название. Этот вариант не самый лучший, хотя его мы тоже рассмотрим. В данной статье я бы хотел предложить самый простой и короткий путь, который при внимательном прочтении мануалов можно найти в документации.
Массив в алфавитном порядке PHP
Способ достаточно прост и заключается в двух шагах: установке локали (setlocal) и непосредственно сортировки массива. Рассмотрим пример с комментариями.
setlocale(LC_ALL, "Russian_Russia.1251"); // установили локаль для русских букв
// пример массива, где слова расположены НЕ по порядку
$example=array("банка","Борис","вид","анкета","егерь","Фёдор","жена","голос");
natcasesort($example, SORT_LOCALE_STRING); // сортируем массив БЕЗ учёта регистра
// ДЛЯ УЧЁТА РЕГИСТРА используйте sort вместо natcasesort
// выводим результат
foreach ($example as $key => $value) echo "$value "; // отобразим только слова, без индекса
>
?>
Демонстрация Скачать исходники
В демонстрации можете посмотреть работу скрипта. При желании можете также скачать архив с файлом.
Если у Вас сервер не на Windows, то нужно будет установить другие локали или сразу несколько:
(LC_ALL, 'ru_RU.CP1251', 'rus_RUS.CP1251', 'Russian_Russia.1251');
// Выведет ru_RU.CP1251 для FreeBSD
// Выведет rus_RUS.CP1251 для линукса
// Выведет Russian_Russia.1251 для Windows
Опережу ответом один из вопросов — локаль для Украины в PHP выглядит так:
Как установить локаль для других кодировок в PHP?
// Устновка локалей для Windows
// Кодировка Windows-1251
setlocale(LC_ALL, 'Russian_Russia.1251');
// Кодировка KOI8-R
setlocale(LC_ALL, 'Russian_Russia.20866');
// Кодировка UTF-8 (использовать осторожно)
setlocale(LC_ALL, 'Russian_Russia.65001');
?>
Второй способ выстроить массив в алфавитном порядке PHP
Если данный способ не устроит и Вы хотите пойти сложным путём, то создайте массив следующего вида:
[0] => а
[1] => б
[2] => в
[3] => г
[4] => д
[5] => е
[6] => ё
[7] => ж
[8] => з
[9] => и
[10] => й
[11] => к
[12] => л
[13] => м
[14] => н
[15] => о
[16] => п
[17] => р
[18] => с
[19] => т
[20] => у
[21] => ф
[22] => х
[23] => ц
[24] => ч
[25] => ш
[26] => щ
[27] => ъ
[28] => ы
[29] => ь
[30] => э
[31] => ю
[32] => я
И переберите по первой букве второй массив.
Первую букву какого-либо элемента массива вычисляем так:
$city[1]='Москва'; // например элемент с индексом 1
$first_letter = mb_substr($city[1],0,1,'UTF-8'); // получим букву "М"
Поскольку работаем с русскими буквами (многобайтной кодировкой), то использовать лучше функцию mb_substr, а в конце лучше точно указать кодировку данных переменной или массива, в нашем случае UTF-8.
Спасибо за внимание! Надеюсь информация была полезна. Если есть вопросы, то пишите в комментариях.
Сортировка массива в php без использования sort(), работающая с русским текстом
Как-то давно проходил собеседование, и там была задача — не используя встроенных функций сортировки, отсортировать массив(вернее список имен из файла) от «а» до «я». Задачу тогда не смог решить и ушел ни с чем… И вот тут недавно вспомнил, стало интересно, каково же, все таки, решение?
Нашел кое-что тут: muruganasm.blogspot.com/2011/01/sort-array-of-string-without-using-php.html. Немного доработал для работы с именами. Например, есть файл listnames.txt:
Salopatan Dolot Lucara Vanibo Xyxelan Ubem Irabon Seboribal Abasixi Abubodul Sasipabi Itatop Latanybor Ocifil Obi Onu Laso pubyl владимир петров Илья бронштейн Александр Мельников алексей шнырюк 512
Для вывода «по-красивее», решил обработать стринги функцией ucwords(). Но, как ни странно, она не захотела работать с русской кодировкой. setlocale() тоже не помогла нисколько. Тут, возможно сыграли настройки сервера. Вобщем, пошел довольно таки сложным путем. Надеюсь, кому-нибудь будет интересно:
+(\s+[А-я])?/i", $str)) < $arr = preg_split("/[\s,]+/",$str); var_dump($arr); $new_str = ""; foreach($arr as $word)< $word = trim($word); $strlen = mb_strlen($word); $word = mb_strtoupper(mb_substr($word,0,1,'UTF-8'),'UTF-8') . mb_strtolower(mb_substr($word,1,$strlen),'UTF-8'); $new_str .= " ".$word; >return trim($new_str); > else return $str; > $array_length = sizeof($str); for($x = 0; $x < $array_length; $x++) < for($y = 0; $y < $array_length; $y++) < if(strcasecmp($str[$x],$str[$y])<0) < $hold = $str[$x]; $str[$x] = $str[$y]; $str[$y] = $hold; >> > $str = array_filter($str); echo "
After sorting
"; print_r($str); ?>
Проверяем, если есть заданный файл. Если есть — читаем и построчно засовываем в массив $str2:
$file_cont = (file_exists($filename))? file_get_contents($filename):die('No such file '.$filename); $str2 = (!empty($file_cont))? preg_split("/[\n,]|[\r,]+/",$file_cont):die('No content was given from '.$filename);
Удаляем пробелы, табуляцию с краев для каждого элемента массива:
Приводим имена в «нормальный» вид. Т.е. иван петров в Иван Петров
$str = array_map("ucwords", $str); $str = array_map("non_en_to_uppercase", $str);
Скорее всего, я где-то перемудрил с функцией non_en_to_uppercase(), но суть ее — проверить, если стринг в русской кодировке, и, если да, принудительно конвертировать первые буквы имени и фимилии в заглавные, а остальные — в строчные.
Далее в двойном цикле с помощью регистронезависимой функции strcasecmp сравниваем элементы массива, и меняем их местами в зависимости от результата сравнения:
$a = 'a'; $b = 'b'; echo strcasecmp($a,$b); //-1
$str = array('Z','c','A','C','E','B','M','N'); $array_length = sizeof($str); for($x = 0; $x < $array_length; $x++) < for($y = 0; $y < $array_length; $y++) < if(strcasecmp($str[$x],$str[$y])<0) < $hold = $str[$x]; $str[$x] = $str[$y]; $str[$y] = $hold; echo "[$x] =>$str[$x]
[$y] => $str[$y]
"; > > >
Напомню, что strcasecmp() не работает нормально с русской кодировкой. буквы «а» и «А» не равны. Поэтому мне пришлось выше приводить имена к единому регистру самописной функцией non_en_to_uppercase($str)
Теперь очистим вывод от пустых значений и печатаем отсортированный массив:
$str = array_filter($str); echo "
After sorting
"; print_r($str);
Php массив сортировка кириллицы
Иногда получается так, что mysql запрос неправильно сортирует текстовые поля с кириллицей. Проблема тут скорее всего в локали, точно не могу сказать (а вообще интересно, может кто знает?).
По идеи достаточно было бы использовать функцию strcmp, но увы, если это касается украинских букв «і»,»ї», то не всё так просто.
Еще одна проблема в том что нельзя просто обращаться к элементам строки по индексу string <4>когда строка в utf-84>
function sort_array($array) < usort($array, 'strcmp_ukr'); return $array; >function strcmp_ukr($v1, $v2) < if (is_array($v1) AND is_array($v2)) < $v1 = reset($v1); $v2 = reset($v2); >$v1 = mb_string_to_array($v1); $v2 = mb_string_to_array($v2); $abc = array('А','Б','В','Г','Ґ','Д','Е','Є','Ж','З','И','І','Ї','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ь','Ю','Я', 'а','б','в','г','ґ','д','е','є','ж','з','и','і','ї','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ь','ю','я'); $len = min(count($v1), count($v2)); for ($i = 0; $i < $len; $i++) < $abc_len = $s1 = $s2 = count($abc); for ($j = 0; $j < $abc_len; $j++) if ($v1[$i] == $abc[$j]) $s1 = $j; for ($k = 0; $k < $abc_len; $k++) if ($v2[$i] == $abc[$k]) $s2 = $k; if ($s1 < $s2) return -1; else if ($s1 >$s2) return 1; > return 0; > function mb_string_to_array($string) < $strlen = mb_strlen($string); while ($strlen) < $array[] = mb_substr($string, 0, 1, 'UTF-8'); $string = mb_substr($string, 1, $strlen, 'UTF-8'); $strlen = mb_strlen($string); >return $array; >
$arr = array(0 => array( title => Вінниця, 10 ), 1 => array( title => Днiпродзержинськ, 41 ), 2 => array( title => Ізмаїл, 11 ), 3 => array( title => Донецьк, 12) );Как отсортировать многоуровневый массив? - Регистронезависимая сортировка для кириллицы?
Подскажите, пожалуйста, как отфильтровать многоуровневый массив по значению вложенного массива 'name' без учета регистра.
Сортировка должна происходить от наиболее полного совпадения (СТРОКА === СТРОКА). Количество вхождений неважно. Главное чтобы было хотя бы одно. Массивы с найденной подстрокой в 'name' сортируются по возрастанию количества символов. Строки без вхождения подстроки должны быть в самом конце массива.
1, 'name' => 'Текст текст СТРОКА текст текст'), array('id' => 2, 'name' => 'СТРОКА'), array('id' => 3, 'name' => 'текст текст'), array('id' => 4, 'name' => 'текстСТРОКАтекст'), ); // Результат должен быть такой: // 1. 'id' => 2, 'name' => 'СТРОКА' // 2. 'id' => 4, 'name' => 'текстСТРОКАтекст' // 3. 'id' => 1, 'name' => 'Текст текст СТРОКА текст текст' // 4. 'id' => 3, 'name' => 'текст текст' $arrayName = array( array('id' => 2, 'name' => 'СТРОКА'), array('id' => 4, 'name' => 'текстСТРОКАтекст'), array('id' => 1, 'name' => 'Текст текст СТРОКА текст текст'), array('id' => 3, 'name' => 'текст текст'), ); ?>
Ответы (2 шт):
usort($arrayName, function ($a, $b) use($substr) < $v = [$a['name'], $b['name']]; foreach($v as &$i) < // дадим вес строке if ($i === $substr) $i = 0; // 0 - равна subst elseif(!(false === strpos($i, $substr))) $i = 1; // 1 - включает подстроку else $i = 2; // 2 - когда подстроки нет >return $v[0]-$v[1]; >); // и отсортируем по этому весу print_r($arrayName);
Общая схема:
1. Временно дополняем массив значениями параметра для сортировки.
2. Сортируем массив по этому параметру.
3. Удаляем параметр из массива.Особенности вычисления параметра:
1. Использованы копии строк в однобайтовой кодировке CP_1251 (Windows-1251).
2. Строки сравниваются в верхнем регистре.
3. Функция cyrtoupper_1251() адаптирована под кириллицу.$substr = 'строкА'; $arrayName = array( array('id' => 1, 'name' => 'Текст текст СТРОКА текст текст'), array('id' => 2, 'name' => 'СТРОКА'), array('id' => 3, 'name' => 'текст текст'), array('id' => 4, 'name' => 'текстСТРОКАтекст'), ); function cyrtoupper_1251($str)< for($i=0; $i223) $ord-=32; $str[$i]= chr($ord); > return strtoupper($str); > print("Исходный массив: "); var_dump($arrayName); $sub_1251 = mb_convert_encoding($substr, 'CP1251'); $sub_upper = cyrtoupper_1251($sub_1251); array_walk($arrayName, function(&$item) use($sub_upper) < // дописываем параметр сортировки $name_1251 = cyrtoupper_1251(mb_convert_encoding($item["name"], 'CP1251')); $len = strpos($name_1251, $sub_upper) === FALSE ? 999 : strlen($name_1251); array_push($item, $len); >); usort($arrayName, function($a,$b) use($sub1251) < // сортируем return end($a)-end($b); >); array_walk($arrayName, function(&$item) < // удаляем array_pop($item); >); print("Отсортированный массив: "); var_dump($arrayName);
Исходный массив: array (size=4) 0 => array (size=2) 'id' => int 1 'name' => string 'Текст текст СТРОКА текст текст' (length=56) 1 => array (size=2) 'id' => int 2 'name' => string 'СТРОКА' (length=12) 2 => array (size=2) 'id' => int 3 'name' => string 'текст текст' (length=21) 3 => array (size=2) 'id' => int 4 'name' => string 'текстСТРОКАтекст' (length=32) Отсортированный массив: array (size=4) 0 => array (size=2) 'id' => int 2 'name' => string 'СТРОКА' (length=12) 1 => array (size=2) 'id' => int 4 'name' => string 'текстСТРОКАтекст' (length=32) 2 => array (size=2) 'id' => int 1 'name' => string 'Текст текст СТРОКА текст текст' (length=56) 3 => array (size=2) 'id' => int 3 'name' => string 'текст текст' (length=21)