{"id":14293,"url":"\/distributions\/14293\/click?bit=1&hash=05c87a3ce0b7c4063dd46190317b7d4a16bc23b8ced3bfac605d44f253650a0f","hash":"05c87a3ce0b7c4063dd46190317b7d4a16bc23b8ced3bfac605d44f253650a0f","title":"\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0432 \u043d\u0438 \u043a\u043e\u043f\u0435\u0439\u043a\u0438","buttonText":"","imageUuid":""}

Распознавание номера телефона из текста транскрибации

Делюсь кейсом по распознаванию номера телефона из текста транскрибации. Люди в диалогах диктуют номер по-разному: кто-то называет каждую цифру по отдельности, кто-то диктует трехзначными цифрами. Составим алгоритм, который поможет правильно составить телефонный номер.

Для начала сделаем функции по определению количества десятков и сотен в числе.

public static int GetDes(int a) { return a % 100 / 10; }         public static int GetDes(string a)         {             return Convert.ToInt32(a) % 100 / 10;         }

Возвращает количество десятков т.е. из чисел 56 и 158 вернет 5

public static int GetSot(int a) { return a / 100; } public static int GetSot(string a) { return Convert.ToInt32(a) / 100; }

Возвращает количество сотен

Чуть-чуть о логике: если друг за другом идут оба числа одного и того же порядка или впереди идет меньшего порядка, например, {7, 9} или {7, 90}, то должна происходить просто склейка 79 или 790 соответственно.

Обратим внимание на последовательность {900, 50, 2}: при наборе, где число 3-его, 2-ого и 1-ого порядков необходимо учитывать, что нужно и склеивать, и складывать числа так, что возможны комбинации 952, 900-52, 900-50-2.

Переходим к алгоритму, с пояснениями:

List<int> listInt = new List<int>() { 900, 50, 2, 60, 7, 80, 2, 40, 6 }; List<string> ls = new List<string>() { listInt[0].ToString() };

Создаем два списка:

- один числовой и заносим туда сразу все числа из номера телефона;

- один строковый, туда сразу заносим первое число.

Так как нулевой элемент мы уже записали, то запускаем цикл, который пойдет со следующего элемента списка и пишем условия, как уже обсуждалось ранее, т.е. что числа одного порядка или следующее число больше. Если условие выполняется, то все элементы строкового списка перезаписываются с дописанным числом-просто склейка строк, если нет, то тоже самое, но плюс еще и надо к каждому ЧИСЛУ из строкового списка прибавить число ИЗ числового списка.

for (int i = 1; i < listInt.Count; i++) { if (listInt[i] > 99 //второе число сотни || GetDes(listInt[i])>0 && GetDes(listInt[i-1])>0 //оба числа десятки || (GetDes(listInt[i]) == 0 && GetDes(listInt[i - 1]) == 0 && GetSot(listInt[i]) == 0 && GetSot(listInt[i - 1]) == 0)// единицы || listInt[i]>listInt[i - 1] //второе больше первого ) { for (int n = 0; n < ls.Count; n++) { ls[n] += listInt[i]; } }// если одного порядка, то склейка else { int steps = ls.Count; for (int n = 0; n < steps; n++) { ls.Add((Convert.ToDecimal(ls[n]) + listInt[i]).ToString()); ls[n] += listInt[i]; } } }

Получится следующий набор возможных номеров:

Дальше убираем лишние элементы списка, где длина строки не равна 10 символам. Реализуем это в C#: в usingах пишем using System.Linq; а в конце следующее условие:

ls = ls.Where(r => r.Length == 10).ToList();

Результатом отработки получился список из 4 возможных номеров:

Итак, мы получили список возможных номеров телефонов из текста транскрибации.

Такой алгоритм применим, например, и для составления инн или чего-либо похожего из списка чисел при задании правил по длине.

0
Комментарии
-3 комментариев
Раскрывать всегда