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

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 1679 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 113 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 113 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 7850 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 533 06.04.18 09:12 Сейчас в теме
(55) А если в номере не десять цифр? Можно просто регуляркой строку обработать
perl -pe 's/\W+//g'

Данным способом любой символ кроме цифры можно убрать
Оставьте свое сообщение
Вакансии
Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)

Программист 1С
Москва
зарплата от 250 000 руб.
Полный день

Программист 1C
Волгоград
зарплата от 200 000 руб.
Полный день

Аналитик
Санкт-Петербург
зарплата от 200 000 руб. до 250 000 руб.
Полный день