Имя: Пароль:
1C
 
Анализ и выстраивание по подпунктам иеарархии.
, ,
0 xipypg2012
 
22.12.14
16:13
Подскажите кто нибудь реализовывал такие алгоритмы,или где можно подсмотреть. пример :

1. Работы
1.1 Строительные работы
1.1.1 Работа 1
1.1.2 Работа 2
1.2 Монтажные работы
1.2.1 Работа 3
1.2.2 работа 4


Грубо говоря такая экселевская таблица, как можно оптимально проанализировать подобную нумерацию , и на базе нее выстроить иерархию
1 vicof
 
22.12.14
16:14
Определяй уровень по количеству точек
2 xipypg2012
 
22.12.14
16:21
Если кто-то чтото на подобие организовывал, либо с цифрами или с буквами скинте плз)
3 vicof
 
22.12.14
16:23
(2) А мож еще дочку председателя колхоза за титьку потрогать дать?
Давай сам делай, вопросы появятся отпишешь, в инете полно примеров работы с экселем.
4 xipypg2012
 
22.12.14
16:29
да эт понятно что не трудно)) просто думать надо)))
5 xipypg2012
 
22.12.14
17:18
Просто по точкам не вариант.........надо анализировать цифры после точек.
6 Лефмихалыч
 
22.12.14
17:20
(0) чо там делать? Это ж в один проход решается. Добро бы они были перемешаны как попало...
7 Лефмихалыч
 
22.12.14
17:21
(4) о чем думать?
Прочел строчку, оторвал все, что до первого пробела - это иерархия. Остальное - данные. Наливай, да пей...
8 НЕА123
 
22.12.14
17:28
Чиселки = СтрЗаменить(СтрПолучитьСтроку(СтрЗаменить(строчкаЭхеля, " ",Символы.ПС),1),".",Символы.ПС);
Для к = 1 по СтрЧислоСтрок(Чиселки)
......
9 Лефмихалыч
 
22.12.14
17:30
+(8) еще к этому надо приделать одно соответствие, в котором ключом будет "#.#.#", а значением - папка справочника. Чтобы запросы в цикле не гонять.
10 Лефмихалыч
 
22.12.14
17:32
единственная заморочка - это, если ты не знаешь, сколько уровней иерархии может быть. Тогда запись в справочник для каждой группы можно делать только после того, как до последних элементов дошел. Что тоже - задача тривиальная, раз они все по иерархии упорядочены
11 cathode
 
22.12.14
17:34
(7) Если сравнивать как строки, то "1.2.10" будет меньше, чем "1.2.2". Придется дополнительно извращаться с элементами иерархии.

(0) Универсальное решение есть, называется алгоритм "натурального" сравнения строк. В PHP, например, есть функция natsort, которая делает именно то, что нужно.

Вот вариант портирования функции сравнения из этой сортировки с C на 1С, но за абсолютную корректность и скорость работы поручиться не могу:

// Проверяет, является ли переданный символ цифрой.
//
// Параметры:
//  Симв - Строка - символ.
//
// Возвращаемое значение:
//  Булево - признак того, что передана цифра.
//
// Примечание: см. libc.isdigit().
//
Функция ЭтоЦифра(Знач Симв)
    
    Перем КодСимв;
    КодСимв = КодСимвола(Симв);
    Возврат (КодСимв <= 57 И КодСимв >= 48);
    
КонецФункции // ЭтоЦифра()

// Проверяет, является ли переданный символ пробельным.
//
// Параметры:
//  Симв - Строка - символ.
//
// Возвращаемое значение:
//  Булево - признак того, что передан пробельный символ.
//
// Примечание: см libc.isspace().
//
Функция ЭтоПробельныйСимвол(Знач Симв)
    
    Возврат (Симв = " "
        Или Симв = Символы.Таб
        Или Симв = Символы.ВК
        Или Симв = Символы.ВТаб
        Или Симв = Символы.НПП
        Или Симв = Символы.ПС);
    
КонецФункции // ЭтоПробельныйСимвол()

// Сравнивает последовательности цифр по их значениям. При этом считается,
// что последовательности не выровнены по длине цифрой 0.
//
// Параметры:
//  Стр1 - Строка - первая строка.
//  Стр2 - Строка - вторая строка.
//
// Возвращаемое значение:
//  Число:
//    -1 - первая строка меньше второй,
//     0 - строки равны,
//    +1 - первая строка больше второй.
//
Функция СравнитьПравыеЦифровыеПоследовательности(Знач Стр1, Знач Стр2)
    
    Перем Сдвиг, ДлинаСтр1, ДлинаСтр2, СчСтр1, СчСтр2, Симв1, Симв2;
    Перем ЭтоЦифраСимв1, ЭтоЦифраСимв2;
    
    Сдвиг = 0;
    
    ДлинаСтр1 = СтрДлина(Стр1);
    ДлинаСтр2 = СтрДлина(Стр2);
    
    Если (ДлинаСтр1 <> 0) И (ДлинаСтр2 <> 0) Тогда
        СчСтр1 = 1;
        СчСтр2 = 1;
        
        Пока Истина Цикл
            Симв1 = Сред(Стр1, СчСтр1, 1);
            Симв2 = Сред(Стр2, СчСтр2, 1);
            ЭтоЦифраСимв1 = ЭтоЦифра(Симв1);
            ЭтоЦифраСимв2 = ЭтоЦифра(Симв2);
            Если Не ЭтоЦифраСимв1 И Не ЭтоЦифраСимв2 Тогда
                Возврат Сдвиг;
                
            ИначеЕсли Не ЭтоЦифраСимв1 Тогда
                Возврат -1;
                
            ИначеЕсли Не ЭтоЦифраСимв2 Тогда
                Возврат +1;
                
            ИначеЕсли Симв1 < Симв2 Тогда
                Если Сдвиг = 0 Тогда
                    Сдвиг = -1;
                КонецЕсли;
                
            ИначеЕсли Симв1 > Симв2 Тогда
                Если Сдвиг = 0 Тогда
                    Сдвиг = +1;
                КонецЕсли;
                
            ИначеЕсли (СчСтр1 >= ДлинаСтр1) Или (СчСтр2 >= ДлинаСтр2) Тогда
                Возврат Сдвиг;
            КонецЕсли;
            
            СчСтр1 = СчСтр1 + 1;
            СчСтр2 = СчСтр2 + 1;
            
        КонецЦикла;
    Иначе
        Возврат Сдвиг;
    КонецЕсли;
    
КонецФункции // СравнитьПравыеЦифровыеПоследовательности()

// Сравнивает последовательности цифр по их значениям. При этом считается,
// что последовательности выровнены цифрами 0.
//
// Параметры:
//  Стр1 - Строка - первая строка.
//  Стр2 - Строка - вторая строка.
//
// Возвращаемое значение:
//  Число:
//    -1 - первая строка меньше второй,
//     0 - строки равны,
//    +1 - первая строка больше второй.
//
Функция СравнитьЛевыеЦифровыеПоследовательности(Знач Стр1, Знач Стр2)
    
    Перем ДлинаСтр1, ДлинаСтр2, СчСтр1, СчСтр2, Симв1, Симв2;
    Перем ЭтоЦифраСимв1, ЭтоЦифраСимв2;
    
    ДлинаСтр1 = СтрДлина(Стр1);
    ДлинаСтр2 = СтрДлина(Стр2);
    
    Если (ДлинаСтр1 <> 0) И (ДлинаСтр2 <> 0) Тогда
        СчСтр1 = 1;
        СчСтр2 = 1;
        
        Пока (СчСтр1 <= ДлинаСтр1) Или (СчСтр2 <= ДлинаСтр2) Цикл
            Симв1 = Сред(Стр1, СчСтр1, 1);
            Симв2 = Сред(Стр2, СчСтр2, 1);
            ЭтоЦифраСимв1 = ЭтоЦифра(Симв1);
            ЭтоЦифраСимв2 = ЭтоЦифра(Симв2);
            Если Не ЭтоЦифраСимв1 И Не ЭтоЦифраСимв2 Тогда
                Возврат 0;
                
            ИначеЕсли Не ЭтоЦифраСимв1 Тогда
                Возврат -1;
                
            ИначеЕсли Не ЭтоЦифраСимв2 Тогда
                Возврат +1;
                
            ИначеЕсли Симв1 < Симв2 Тогда
                Возврат -1;
                
            ИначеЕсли Симв1 > Симв2 Тогда
                Возврат +1;
            КонецЕсли;
            
            СчСтр1 = СчСтр1 + 1;
            СчСтр2 = СчСтр2 + 1;
        КонецЦикла;
    КонецЕсли;
    
    Возврат 0;

КонецФункции // СравнитьЛевыеЦифровыеПоследовательности()

// Выполняет "натуральное" сравнение строк с учетом значений
// последовательностей цифр в исходных строках.
//
// Параметры:
//  Стр1 - Строка - первая строка.
//  Стр2 - Строка - вторая строка.
//  УчитыватьРегистр - Булево - учитывать регистр букв.
//
// Возвращаемое значение:
//  Число:
//    -1 - первая строка меньше второй,
//     0 - строки равны,
//    +1 - первая строка больше второй.
//
Функция СравнитьСтрокиНатурально(Знач Стр1, Знач Стр2, Знач УчитыватьРегистр = Истина) Экспорт
    
    Перем РезультатСравнения, СчСтр1, СчСтр2, Симв1, Симв2;
    
    СчСтр1 = 1;
    СчСтр2 = 1;
    
    Пока Истина Цикл
        Симв1 = Сред(Стр1, СчСтр1, 1);
        Симв2 = Сред(Стр2, СчСтр2, 1);
        
        // "Прогоняем" пробельные символы первой строки.
        Пока ЭтоПробельныйСимвол(Симв1) Цикл
            СчСтр1 = СчСтр1 + 1;
            Симв1 = Сред(Стр1, СчСтр1, 1);
        КонецЦикла;
        
        // "Прогоняем" пробельные символы второй строки.
        Пока ЭтоПробельныйСимвол(Симв2) Цикл
            СчСтр2 = СчСтр2 + 1;
            Симв2 = Сред(Стр2, СчСтр2, 1);
        КонецЦикла;
        
        Если ЭтоЦифра(Симв1) И ЭтоЦифра(Симв2) Тогда
            Если Симв1 = "0" Или Симв2 = "0" Тогда
                РезультатСравнения = СравнитьЛевыеЦифровыеПоследовательности(Сред(Стр1, СчСтр1), Сред(Стр2, СчСтр2));
                Если РезультатСравнения <> 0 Тогда
                    Возврат РезультатСравнения;
                КонецЕсли;
            Иначе
                РезультатСравнения = СравнитьПравыеЦифровыеПоследовательности(Сред(Стр1, СчСтр1), Сред(Стр2, СчСтр2));
                Если РезультатСравнения <> 0 Тогда
                    Возврат РезультатСравнения;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
        
        Если (Симв1 = "") И (Симв2 = "") Тогда
            Возврат 0;
        КонецЕсли;
        
        Если Не УчитыватьРегистр Тогда
            Симв1 = ВРег(Симв1);
            Симв2 = ВРег(Симв2);
        КонецЕсли;
        
        Если Симв1 < Симв2 Тогда
            Возврат -1;
        ИначеЕсли Симв1 > Симв2 Тогда
            Возврат +1;
        КонецЕсли;
        
        СчСтр1 = СчСтр1 + 1;
        СчСтр2 = СчСтр2 + 1;
            
    КонецЦикла;
    
КонецФункции // СравнитьСтрокиНатурально()

Это правда, только сравнение строк. Сортировку нужно будет сделать самостоятельно. Если скорость будет маленькая, функции ЭтоЦифра и ЭтоПробельныйСимвол можно инлайнить.
12 cathode
 
22.12.14
17:47
(0) Блин, надо было внимательно прочитать, чего человек хочет...
Короче, (11) - это не совсем в ту степь.
Отсортировать-то строки он отсортирует, а вот задачу построения иерархии не решает.