Ускорить код?

1. DenisCh 13.02.18 10:49 Сейчас в теме
Есть такая функция
Функция преобрНТ(ЗНАЧ нт)
	Если Лев(нт, 2) = "+7" Тогда
		нт = сред(нт, 3);
	ИначеЕсли Лев(нт, 2) = "+8" Тогда
		нт = сред(нт, 3);
	ИначеЕсли Лев(нт, 1) = "8" Тогда
		нт = сред(нт, 2);
	КонецЕсли;
	стр = "";
	Для сч = 1 по СтрДлина(нт) ЦИкл
		см = Сред(нт, сч, 1);
		Если КодСимвола(см)>=КодСимвола("0") И КодСимвола(см)<=КодСимвола("9") Тогда
			стр = стр + см;
		КонецЕсли;
	КонецЦикла;
	
	возврат стр;
КонецФункции
Показать


Приводит номер телефона к каноническому виду (без +7/+8/8).
Работает как-то долго.
Вот эти две строки
см = Сред(нт, сч, 1);
		Если КодСимвола(см)>=КодСимвола("0") И КодСимвола(см)<=КодСимвола("9") 


Как можно это дело улучшить?
По теме из базы знаний
Ответы
Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
4. yurazyuraz 13.02.18 11:02 Сейчас в теме
(1)
попробовать оптимизировать
Результат = СтрЗаменить (  СтрЗаменить (нт, "+7", " ") , "+8", " "); 
// этот код чуть быстрее работает
7. yurazyuraz 13.02.18 11:11 Сейчас в теме
(4)
что касается первой восьмерки - то вот такой код - значительно быстрее традиционного
везде где можно замените

Если ( тут какие то условия ) тогда
...
КонецЕсли;

на вот такой код

Результат = ?( Лев(нт, 1) = "8","",нт )

Вы будете возможно удивлены , но это код работает быстрее.
8. pm74 199 13.02.18 11:12 Сейчас в теме
15. yurazyuraz 13.02.18 11:23 Сейчас в теме
(8) при желании можете замерить, если у Вас есть исследовательская искорка, прогоните в большом цикле:
я просто уже знаю , что 1-й вариант быстрее.


1) этот код

нт=  ?( Лев(нт, 2) = "+7","",нт);


2) и вот такой код

Если Лев(нт, 2) = "+7" Тогда
     нт = сред(нт, 3);
КонецЕсли;
6. catena 110 13.02.18 11:07 Сейчас в теме
(1)
КодСимвола(см)>=КодСимвола("0") И КодСимвола(см)<=КодСимвола("9")


Найти("0123456789",см)
SlavaKron; корум; ipoloskov; +3 Ответить
13. DenisCh 13.02.18 11:22 Сейчас в теме
(6) Как вариант. Попробую
9. pm74 199 13.02.18 11:16 Сейчас в теме
(1) а если будет пробел+7 ?
14. DenisCh 13.02.18 11:23 Сейчас в теме
(9) Там снаружи идёт сокрлп(), так что первого пробела не будет
18. yurazyuraz 13.02.18 11:29 Сейчас в теме
(14)

ну видите Петр , я как в воду смотрел. Пробелов нет
21. pm74 199 13.02.18 11:40 Сейчас в теме
(18)да там все что угодно может быть точка например ибо строка, что будете проверять на точки перед обработкой ?
24. kuzev 47 13.02.18 11:45 Сейчас в теме
Функция преобрНТ(ЗНАЧ нт) 
	стр = ""; 
	Для сч = 1 по СтрДлина(нт) ЦИкл 
		см = Сред(нт, сч, 1); 
		Если см>="0" И см<="9" Тогда 
			стр = стр + см; 
		КонецЕсли;
	КонецЦикла;

	возврат Прав(стр,10); 
КонецФункции
Показать
17. yurazyuraz 13.02.18 11:28 Сейчас в теме
(9) если автор ставит Лев(нт, 2) , значит у него не бывает впереди пробела.
Любая программа опирается на какие то условия. В его условиях впереди пробела быть не может, возможно перед тем как положить данные в базу или при передаче параметров, он уже очистил от лидирующих пробелов , мы видим лишь некие входные условия.
Мы же понимаем , что если отключат электричество , то вообще программа не отработает, это кстати тоже условие работы программы.
54. DrAku1a 1715 22.02.18 04:14 Сейчас в теме
(1) На вскидку:
Перед циклом:
КодСимвола0 = КодСимвола("0");
КодСимвола9 = КодСимвола("9"); 
В цикле:
см = КодСимвола(Сред(нт, сч, 1));
Если см>=КодСимвола0 И см<=КодСимвола9
2. nayd 9 13.02.18 10:59 Сейчас в теме
Этот код на клиенте делается? А если перенести на сервер?
11. DenisCh 13.02.18 11:21 Сейчас в теме
(2) У меня обычные формы. Не хочется ради этого конфигурацию менять.
3. TODD22 18 13.02.18 11:01 Сейчас в теме
Работает как-то долго.

5 секунд? 1 секунду? Или сколько?
12. DenisCh 13.02.18 11:22 Сейчас в теме
(3) 100 000 записей обрабатывает порядка 2 минут
5. caponid 13.02.18 11:06 Сейчас в теме
ну и вынести вычисление КодСимвола("0") И КодСимвола("9") за пределы цикла...
10. protexprotex 114 13.02.18 11:17 Сейчас в теме
Если КодСимвола(см)>=КодСимвола("0") И КодСимвола(см)<=КодСимвола("9")

КодСимвола("0") и КодСимвола("9") вычислить один раз и использовать через общие переменные модуля.

Также: Если Лев(нт, 2) = "+7" Тогда - все заменить на СтрЗаменить.
16. Cooler 22 13.02.18 11:24 Сейчас в теме
(10)
КодСимвола("0") и КодСимвола("9") вычислить один раз и использовать через общие переменные модуля.
А что, строковые переменные в 8-ке уже нельзя сравнивать на "больше-меньше"?

Если см>="0" И см<="9" Тогда 
   стр = стр + см; 
КонецЕсли;
корум; karpik666; KapasMordorov; kuzev; +4 Ответить
19. yurazyuraz 13.02.18 11:31 Сейчас в теме
(16)
лучше так

Если Число(см)>= 0 И Число(см)<=9 Тогда

..
кстати очень изящно!

ОПС - так не отработает если нарвется на "+"
20. DenisCh 13.02.18 11:35 Сейчас в теме
(19) там ещё - может быть. Например 123-45-67
23. yurazyuraz 13.02.18 11:44 Сейчас в теме
(20)
Ну в теории можно зачистку сделать оставить только цифры.
Вообще это у вас уложено в базу ? может зачистить один раз , разово , перед укладкой в базу.
26. DenisCh 13.02.18 11:46 Сейчас в теме
(23) Это лежит в базе. Но а) телефон нужен в человекочитаемом виде и б) процедура вызывается не каждые 5 секунд, чтобы изменённые данные хранить в базе и дублировать информацию.
В принципе после советов тут скорость поднялась на ~20%. Дальше уже другие моменты роялять...
27. yurazyuraz 13.02.18 11:48 Сейчас в теме
(26) это после

нт= ?( Лев(нт, 2) = "+7","",нт);
29. DenisCh 13.02.18 11:52 Сейчас в теме
(27)
Функция преобрНТ(ЗНАЧ нт)
	
	нт = СтрЗаменить(нт, "+7", "");
	нт = СтрЗаменить(нт, "+8", "");
	
	Если Лев(нт, 1) = "8" Тогда
		нт = сред(нт, 2);
	КонецЕсли;
	стр = "";
	дл = СтрДлина(нт);
	Для сч = 1 по дл ЦИкл
		см = Сред(нт, сч, 1);
		Если Найти("0123456789", см) > 0 Тогда
		//Если КодСимвола(см)>=КодСимвола("0") И КодСимвола(см)<=КодСимвола("9") Тогда
			стр = стр + см;
		КонецЕсли;
	КонецЦикла;
	
	возврат стр;
КонецФункции
Показать
33. yurazyuraz 13.02.18 11:58 Сейчас в теме
(29) как я понял это уже дало 20% по скорости. Но тут еще можно порезвиться по оптимизации.

Но самый лучший вариант посадить ОДИН РАЗ в базу одни цифры.
А выводить пользователю форматно, это будет более оптимальное решение.
И у Вас просто исчезнет подобна процедура.
37. spacecraft 13.02.18 12:01 Сейчас в теме
(29)
нт = СтрЗаменить(нт, "+7", "");
нт = СтрЗаменить(нт, "+8", "");

повезет, если в базе нет таких данных:
"8+910+123+71+82"
38. yurazyuraz 13.02.18 12:02 Сейчас в теме
(37) Круто, а еще бывают невидимые символы
40. DenisCh 13.02.18 12:05 Сейчас в теме
(37) если будут - это будет вина менеджеров. А не моя
43. spacecraft 13.02.18 12:07 Сейчас в теме
(40) а зачем вообще все эти изыски?
Если там не числовые символы, то это ведь вина менеджера, а не программиста...
yurazyuraz; +1 Ответить
44. DenisCh 13.02.18 12:13 Сейчас в теме
(43) искать данные надо. Но и вводить данные тоже нужно правильно.
yurazyuraz; +1 Ответить
46. yurazyuraz 13.02.18 12:15 Сейчас в теме
(44) вот истину глаголите! лучше потратить усилия над правильным вводом
47. spacecraft 13.02.18 12:19 Сейчас в теме
(44) есть 3 вида ошибок.
1. Ошибка на этапе компиляции.
2. Ошибка во время работы.
3. Ошибка не отслеживаемая, возможно приводящая к порче данных.

Третья ошибка самая опасная из всех. Мина замедленного действия.
45. yurazyuraz 13.02.18 12:14 Сейчас в теме
(40)

ну в любом случае, если юзер-менеджер некооректно вводит , надо просто программно не дать ему ввести кривой номер в базу.
Поймите , лучше на входе данные изначально ввести правильно , чем потом бороться с мельницами.
48. yurazyuraz 13.02.18 12:24 Сейчас в теме
(29)
(30)

тут надо понимать - для чего вы ее запускаете ?

если ее можно например запускать рано утром - до начала рабочего дня
или поздно вечером или еще лучше ночью - то в принципе борьбы такой делать и не надо.

--

но идеально - это правильное проектирование - т.е. НЕ ДОПУСКАТЬ кривой ввод данных изначально.
49. DenisCh 13.02.18 12:34 Сейчас в теме
(48) Её запускают тогда, когда нужно начальнику. Не в моих силах на это повлиять.
И вообще - вопрос "правильного" хранения телефонов нужно адресовать в Москву.
Ибо ради такой задачки переделывать всю подсистему хранения контактной информации - мне за это не заплатят.
50. yurazyuraz 13.02.18 13:06 Сейчас в теме
(49) Если база порядка 100-300тыс записей , обработка на 100тыс порядка 2 минут - то не страшно, а если несколько миллионов то это уже серьезно. В моем случае у меня была база порядка 4 терабайт , в некоторых таблицах сотни миллионов записей, база не 1С. Подобная обработка была бы неприемлема. Если ничего нельзя сделать с приведением данных к нормальному виду и начальник не готов идти на оптимизацию хранения данных. Остается только писать изящные решения для борьбы с последствиями , тем более что именно за них и платят.
28. yurazyuraz 13.02.18 11:51 Сейчас в теме
(26)

Вообще в базу можно уложить как раз в виде 4955555255
но вывод делать форматно 495-555-52-55
30. DenisCh 13.02.18 11:52 Сейчас в теме
(28) можно. Но это ради задачи, которая раз в три дня запускается - овчинка выделки.
22. Cooler 22 13.02.18 11:42 Сейчас в теме
(19) В номерах телефонов группы цифр очень любят разделять пробелами или дефисами. Проверьте на них свое "изящное" решение.

И вообще тема - баян баянов, уже немало копий сломано: https://forum.infostart.ru/forum9/topic114710/
25. yurazyuraz 13.02.18 11:45 Сейчас в теме
(22) до того как начинать - можно оставить в данных только цифры и проблем будет меньше
31. yurazyuraz 13.02.18 11:53 Сейчас в теме
(22)

Вообще в базу можно уложить как раз в виде 4955555255 , но приятный человеческий вывод делать форматно 495-555-52-55 , будет вообще без обработки.
32. kuzev 47 13.02.18 11:55 Сейчас в теме
(31) а как же 1234-55-52-55 и 12345-5-52-55? =)
34. pm74 199 13.02.18 11:58 Сейчас в теме
36. yurazyuraz 13.02.18 12:01 Сейчас в теме
(34) Веселей будет если цифр в номере не 10 будет а 12 , 15 , 50 :-)
35. yurazyuraz 13.02.18 11:59 Сейчас в теме
(32) форматный вывод не с лева делать а справа лучше , всегда будет как надо
42. protexprotex 114 13.02.18 12:07 Сейчас в теме
(16) Можно. Но есть одно но - транслятор перед сравнением букв производит конвертацию буквенного представления в числовой (т.к. в регистрах процессора хранятся не буквы, а числа). Т.е. все равно сравниваются не буквы как таковые, а числа. Т.е. см>="0" и КодСимвола(см)>=Перем0, где Перем0 уже присвоено КодСимвола("0") должно работать быстрее. Т.к. тут производится только одно преобразование КодСимвола(см). Но проверить это надо - т.к. транслятор может оптимизировать по другому.
39. Cooler 22 13.02.18 12:05 Сейчас в теме
М-да. В итоге из ветки получилась еще одна иллюстрация на тему: "Почему 1Cников не считают настоящими программистами?"
корум; +1 Ответить
41. yurazyuraz 13.02.18 12:06 Сейчас в теме
(39) мне интересно почему ? кстати я не 1С ник
51. pm74 199 13.02.18 13:20 Сейчас в теме
(39) да почему собственно , тут (24) уже написали правильный код
52. ildarovich 7861 15.02.18 18:41 Сейчас в теме
(0) Если включен режим совместимости 8.3.6 и позже, то для очистки номера от мусора (всех нецифровых символов) достаточно вот такого кода:
ТолькоЦифры = СтрСоединить(СтрРазделить(СтрокаСЦифрами, СтрСоединить(СтрРазделить(СтрокаСЦифрами, "0123456789"))));
	
Это должно дать ускорение.
корум; pm74; Абушев; independ; +4 Ответить
53. user916475 15.02.18 19:20 Сейчас в теме
не помогли советы в комметариях, может есть еще способы?
55. smilemanrus 3 22.02.18 09:52 Сейчас в теме
А если использовать регулярные выражения? По ссылке выше были примеры, сначала отбираем только цифры регулярным выражением, а потом справа отбираем 10 символов
56. Shmell 535 06.04.18 09:12 Сейчас в теме
(55) А если в номере не десять цифр? Можно просто регуляркой строку обработать
perl -pe 's/\W+//g'

Данным способом любой символ кроме цифры можно убрать
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот