Удалить дубликаты, предпочитая регистр (php)

12
toxic steel
На сайте с 28.12.2007
Offline
175
1213

Коллеги, есть здоровенный массив PHP, в котором встречаются дубликаты значений в разных регистрах:

Москва

москва

Санкт-Петербург

санкт-петербург

СНТ

снт

Приозерск

улус

Т.е. заглавная буква может быть не только в начале, но в середине, или вообще - целиком из заглавных букв.

Мне нужно удалить дубликаты в нижнем регистре, сохранив значения, где встречается верхний регистр. Дубликата может не быть, тогда оставляем то, что есть.

Т.е. на выходе из примера я должен получить

Москва

Санкт-Петербург

СНТ

Приозерск

улус

Буду признателен за идеи как сделать это поизящней! :drink:

Есть отличные, недорогие рекламные места на агрофоруме (http://farmerforum.ru/viewtopic.php?t=1725)! Клуб истинных ценителей денег (http://coinshunter.ru/).
S
На сайте с 30.09.2016
Offline
469
#1

Не знаю насчёт изящности, но по 1 штуке можно оставить так:


<?php
$arr = array(
'Москва',
'санкт-петербург',
'снт',
'москва',
'Санкт-Петербург',
'СНТ',
'снт',
'Приозерск',
'СНТ',
'Москва',
'улус',
'москва',
'сНт',
'Москва',
'СНТ'
);

foreach($arr as $item){
$low[] = mb_strtolower($item);
}

foreach($arr as $key=>$val){
if(($e=array_search(mb_strtolower($val), $low)) !== false && $e !== $key){
if(mb_substr($arr[$key], 0, 1) == mb_strtolower(mb_substr($arr[$key], 0, 1))){
unset($arr[$key]);
unset($low[$key]);
}else{
unset($arr[$e]);
unset($low[$e]);
}
}
}

Но из значений типа "МосквА" или "Санкт-петербург" оно будет выбирать первые попавшиеся, которые начинаются с заглавной буквы.

Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
LEOnidUKG
На сайте с 25.11.2006
Offline
1723
#2

1. Всё закинуть в нижний регистр

2. Очистить от дубликатов

3. Поднять первую букву

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/
IL
На сайте с 09.12.2009
Offline
124
#3
LEOnidUKG:
1. Всё закинуть в нижний регистр
2. Очистить от дубликатов
3. Поднять первую букву

Не получится:

СНТ

снт

по данному алгоритму не пройдет

Devvver
На сайте с 02.07.2008
Offline
663
#4

Копируем массив в другой и переводим все в нижний регистр(в втором массиве).

Получаем строку 1 массива и записываем его в переменную темп.

Проганяем по массиву2 проверку есть ли там темп(в нижнем регистре).

Если есть - записываем темп в массив номер3

И так по всему списку.

Мой блог. Все о создании сайтов,Seo и СДЛ ( https://devvver.ru/ ) Мой SEO телеграм канал https://t.me/seobloggers
Samail
На сайте с 10.05.2007
Offline
361
#5

$arr = array('Москва','санкт-петербург','снт','москва','Санкт-Петербург','липецк','лиПецк','снт','Иваново','СНТ','Москва','москва','сНт','МосКва','СНТ','Липецк');
natsort($arr);

function strtolower_utf8($a){
return mb_strtolower($a,'UTF-8');
}
function array_iunique($array) {
return array_intersect_key($array,array_unique(array_map("strtolower_utf8",$array)));
}

$arr=array_iunique($arr);
print_r($arr);

Array ( [8] => Иваново [15] => Липецк [13] => МосКва [9] => СНТ [4] => Санкт-Петербург )

LEOnidUKG
На сайте с 25.11.2006
Offline
1723
#6

Samail, сильно. Функцию array_intersect_key вообще ни разу не пользовал, интересная вещица.

---------- Добавлено 12.04.2019 в 17:57 ----------

Вот только в этом будет косяк:

Т.е. заглавная буква может быть не только в начале, но в середине, или вообще - целиком из заглавных букв.

При таком массиве:

$arr = array('москва','санкт-петербург','снт','москва','Санкт-Петербург','липецк','лиПецк','снт','Иваново','СНТ','Москва','москва','сНт','МосКва','СНТ','Липецк');

Будет

Array

(
[8] => Иваново
[15] => Липецк
[13] => МосКва
[9] => СНТ
[4] => Санкт-Петербург
)
Samail
На сайте с 10.05.2007
Offline
361
#7

LEOnidUKG, сама функция из интернета, моя идея была в том что-бы массив сначала отсортировать с учётом регистра.

LEOnidUKG
На сайте с 25.11.2006
Offline
1723
#8

Если никто не против я свой вариант выложу:


$arr = array('москва','санкт-петербург','снт','москва','Санкт-Петербург','липецк','лиПецк','снт','Иваново','СНТ','Москва','москва','сНт','МосКва','СНТ','Липецк','санкт-петерБург');

$arr=array_unique(array_map("strtolower_utf8",$arr));

function strtolower_utf8($str){

if (mb_strlen($str,'UTF-8')<=3) {
$str = mb_convert_case($str, MB_CASE_UPPER, "UTF-8");
} else {
$str = mb_convert_case($str, MB_CASE_TITLE, "UTF-8");
}
return $str;
}
print_r($arr);
Samail
На сайте с 10.05.2007
Offline
361
#9
LEOnidUKG:
Вот только в этом будет косяк:

Цитата:
Т.е. заглавная буква может быть не только в начале, но в середине, или вообще - целиком из заглавных букв.

Может ТС и нужно сохранить заглавную букву в середине если она там есть. Это у меня МосКва, а в настоящем массиве может заглавная и в тему.

if (mb_strlen($str,'UTF-8')<=3) - а если будет СНТО ...или Уфа?

LEOnidUKG
На сайте с 25.11.2006
Offline
1723
#10
Может ТС и нужно

Это он уже пусть решает :)

if (mb_strlen($str,'UTF-8')<=3) - а если будет СНТО?

Если это нужно одноразово, то там можно обойтись и str_replace, думаю мало там таких значений, которые должны быть все с большой буквы.

---------- Добавлено 12.04.2019 в 18:23 ----------

Samail:
Может ТС и нужно сохранить заглавную букву в середине если она там есть. Это у меня МосКва, а в настоящем массиве может заглавная и в тему.
if (mb_strlen($str,'UTF-8')<=3) - а если будет СНТО ...или Уфа?

Ну переделаем на:

$arr = array('москва','санкт-петербург','снт','москва','Санкт-Петербург','липецк','лиПецк','снт','Иваново','СНТ','Москва','москва','сНт','МосКва','СНТ','Липецк','санкт-петерБург','УльянОвск','уфА');

$arr=array_unique(array_map("strtolower_utf8",$arr));

function strtolower_utf8($str){
$minicity=array('снт','снто'); // Исключения

if (in_array(mb_convert_case($str, MB_CASE_LOWER, "UTF-8"),$minicity)) {
$str = mb_convert_case($str, MB_CASE_UPPER, "UTF-8");
} else {
$str = mb_convert_case($str, MB_CASE_TITLE, "UTF-8");
}
return $str;
}
print_r($arr);

Последняя редакция :)

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий