gifts2017

Группировка текста

Опубликовал Яков Коган (Yashazz) в раздел Программирование - Практика программирования

Большой текст с многочисленными отступами... Сделаем группировки по этим отступам и свернём их для удобства чтения!

Был у меня процесс, выдававший очень неслабый текст протокола действий, под 400 тыщ строк. И смотреть его глазками стало невыносимо, а иной анализ результата не давал. И решил я сгруппировать текст, просто по отступам, которые, вдобавок, имели свой смысл и логику. Что позволяет свернуть группировки? Да, обычный моксель. Результатом стала функция, превращающая текст в табличный документ, где все имеющиеся отступы сгруппированы. Функция портируемая; под УФ не проверял, но должна пойти. 


Функция СгруппироватьТекст(Знач рТекстИлиСтрока,рСохранятьОтступы=Истина,дТекста=Неопределено)
   
дТекста=Новый ДеревоЗначений;
   
дТекста.Колонки.Добавить("Отступ",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(3,0)));
   
дТекста.Колонки.Добавить("Текст",Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(0)));
   
дТекста.Колонки.Добавить("Единица",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(1,0)));
   
//
   
Если ТипЗнч(рТекстИлиСтрока)=Тип("Строка") Тогда
       
рТекст=Новый ТекстовыйДокумент;
       
рТекст.УстановитьТекст(рТекстИлиСтрока);
    КонецЕсли;

   
рТекущаяВетка=дТекста.Строки.Добавить(); // корневая
   
квостр=рТекст.КоличествоСтрок();
   
квоиз=" из "+СокрЛП(квостр);
    Для
й=1 По квостр Цикл
       
#Если Клиент Тогда
           
ОбработкаПрерыванияПользователя();
           
Состояние("Подготовка: строка "+Строка(й)+квоиз);
       
#КонецЕсли
       
стро=рТекст.ПолучитьСтроку(й);
        Если
ПустаяСтрока(стро) Тогда
           
рРодитель=рТекущаяВетка.Родитель; // пишем на тот же уровень
           
рОтступ=рТекущаяВетка.Отступ; строБезОтступа="";
        Иначе
           
рОтступ=0; строБезОтступа="";
            Для
ы=1 По СтрДлина(стро) Цикл
               
сим=Сред(стро,ы,1);
                Если
сим=" " или сим=Символы.НПП или сим=Символы.Таб Тогда
                   
рОтступ=рОтступ+1;
                Иначе
                   
строБезОтступа=Сред(стро,ы); Прервать;
                КонецЕсли;
            КонецЦикла;
           
// ищем ветку с подходящим числом отступов
           
Пока Истина Цикл
               
#Если Клиент Тогда
                   
ОбработкаПрерыванияПользователя();
               
#КонецЕсли
               
Если рТекущаяВетка.Отступ=рОтступ Тогда // стыкуемся к её родителю
                   
рРодитель=рТекущаяВетка.Родитель; Прервать;
                ИначеЕсли
рТекущаяВетка.Отступ<рОтступ Тогда // стыкуемся к ней
                   
рРодитель=рТекущаяВетка; Прервать;
                Иначе
// идём выше
                   
рТекущаяВетка=рТекущаяВетка.Родитель;
                    Если
рТекущаяВетка=Неопределено Тогда Прервать КонецЕсли;
                КонецЕсли;
            КонецЦикла;
            Если не
ЗначениеЗаполнено(рРодитель) Тогда
               
рРодитель=дТекста.Строки.Получить(0);
            КонецЕсли;
        КонецЕсли;
       
// добавляем
       
рВетка=рРодитель.Строки.Добавить();
       
рВетка.Отступ=рОтступ;
       
рВетка.Текст=строБезОтступа;
       
рВетка.Единица=1;
       
рТекущаяВетка=рВетка;
    КонецЦикла;
   
//
   
рТекст.Очистить(); // а чтоб оперативку не занимал
   
рТекст=""; рТекстИлиСтрока="";

   
тд=Новый ТабличныйДокумент;

   
// строки в результатной выборке поиска расположены ровно в том же порядке, что и в исходном тексте
   
мстро=дТекста.Строки.НайтиСтроки(Новый Структура("Единица",1),Истина);
   
квоиз=" из "+СокрЛП(мстро.Количество());
   
СтарРодитель=Неопределено;
    Для
й=1 По мстро.Количество()-1 Цикл
       
#Если Клиент Тогда
           
ОбработкаПрерыванияПользователя();
           
Состояние("Вывод: строка "+Строка(й)+квоиз);
       
#КонецЕсли
       
стро=мстро.Получить(й-1);
        Если
стро.Родитель<>СтарРодитель Тогда
            Если
СтарРодитель<>Неопределено Тогда
               
рРодитель=СтарРодитель;
               
рТекУровень=стро.Уровень(); // хотя можно и через убывание всё того же Отступа, но так точнее
               
Пока рТекУровень<=рРодитель.Уровень() Цикл
                   
// кончилась предыдущая подветка, надо её сгруппировать, группируем с й-квоСтрок по й-1,
                    // где квоСтрок - это общее кол-во всех строк, входящих в ветку на различных уровнях итого.
                   
квоСтрок=рРодитель.Строки.Итог("Единица",Истина);
                   
// идём дальше - если кончился более чем один уровень вложенности, надо сгруппировать их все.
                    // можно, конечно, накапливать квоСтрок вверх по уровням - флаг в руки желающим оптимизации)
                   
тд.Область(й-квоСтрок,,й-1).Сгруппировать();
                   
рРодитель=рРодитель.Родитель;
                    Если
рРодитель=Неопределено Тогда Прервать КонецЕсли;
                КонецЦикла;
            КонецЕсли;
           
СтарРодитель=стро.Родитель;
        КонецЕсли;
       
//
       
рОбласть=тд.Область(й,1);
       
рОбласть.Текст=стро.Текст;
        Если
рСохранятьОтступы Тогда
           
рОбласть.Отступ=стро.Отступ; // если была табуляция, то получится перекос, т.к. пробел поуже табулятора.
       
КонецЕсли;
    КонецЦикла;
   
#Если Клиент Тогда
       
Состояние("");
   
#КонецЕсли

   
тд.Область(1,1,тд.ВысотаТаблицы,1).ШиринаКолонки=100;
   
тд.ОтображатьГруппировки=Истина;
   
тд.ОтображатьСетку=Ложь;
   
// а всякое раскрытие группировок - уже при показе, если будет надо
   
Возврат тд;
КонецФункции

Напоминает всем нам известный редактор модулей 1С по эффекту работы))).  Кому сгодится - будет хорошо)

P.S. Можно и без дерева значений, но оно мне тоже было нужно.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Val Yan (valvit) 18.06.14 08:31
Если ТипЗнч(рТекстИлиСтрока)=Тип("Строка") Тогда нет блока ИНАЧЕ. Если не строка вываливается по ошибке. на картинке результат обработки. По-моему первая (корневая) группировка не отработала. Хотя это же не комерческий продукт ;)
Прикрепленные файлы:
2. mikhailovaew (mikhailovaew) 19.06.14 11:47
О, здорово, можно модули типовых в нечто удобочитаемое превращать!
3. Яков Коган (Yashazz) 19.06.14 16:01
(1) Знаю, знаю ((( Я сперва не то запостил, а отредактировать уже не вышло по техническим причинам. Конечно, там "рТекст=рТекстИлиСтрока" должно быть, в ветке "Иначе", но опять это править - я повешусь (.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа