Имя: Пароль:
1C
1С v8
Обход двумерного массива рекурсией
0 Vanyok
 
30.04.15
06:13
Дан двумерный массив.
Например:
1, 2, 3
а, б
z
Надо составить всевозможные комбинации:
1аz, 1бz, 2az, 2бz, 3az, 3бz

Начинаем с первого элемента
ВыбратьЭлемент(0,0,ДвумерныйМассив,"")

Функция ВыбратьЭлемент(знач х,знач у,Массив,ОбщийМассивЗначений)
    Пока у <= Массив[х].Количество()-1 Цикл//обход строк
        ОбщийМассивЗначений = ОбщийМассивЗначений + Строка(Массив[х][у]) + " ";
        х = х + 1;
        Если х > Массив.Количество()-1 Тогда
            х = х - 1;
            Сообщить(ОбщийМассивЗначений);
            ОбщийМассивЗначений = "";
        КонецЕсли;    
        у = у + 1;
        ВыбратьЭлемент(х,у,Массив,ОбщийМассивЗначений);
    КонецЦикла;
КонецФункции

Люди добрые, подскажите, чяднт?
1 Simod
 
30.04.15
06:44
Зачем тут рекурсия?
2 Vanyok
 
30.04.15
06:56
(1) Предложите вариант.
Может быть случайное количество элементов, не обязательно так как в примере.
3 GenAcid
 
30.04.15
07:08
В (0) не двумерный массив, а 3 одномерных

Двумерный массив вот:
1, 2, 3
а, б, _
z, _, _
4 Vanyok
 
30.04.15
07:18
(3) где Вы там третье измерение нашли?
Все элементы обходятся через Массив[х][у]
5 User_Agronom
 
30.04.15
07:34
(4) У тебя не двухмерный массив, одномерный массив, элементы которого массивы.
6 Vanyok
 
30.04.15
07:37
(3) (5) Ребята, согласен с вами!
Как получить все возможные варианты?
7 1Сергей
 
30.04.15
07:41
У многомерного массива Количество значений в каждом измерении постоянно, у тебя для первой строки 3 колонки, для второй 2, для третьей одна.
Ну, не суть.

Можно без рекурсии
Для х = 1 по Изм1 Цикл
    Для у = 1 по Изм2 Цикл
        ...
8 Vanyok
 
30.04.15
07:47
(7) Обойти все элементы можно.
Но надо найти все комбинации элементов, как в примере.
9 фобка
 
30.04.15
07:58
берем (7) и развиваем

МасОбщ = Новый Массив;
Для Каждого Элт1 Из Мас1 Цикл
  Для Каждого Элт2 Из Мас2 Цикл
    МасОбщ = ""+Элт1+Элт2; //тут сам думаешь какие значения нужны
   КонецЦикла;
КонецЦикла;
10 фобка
 
30.04.15
07:59
+9 для 3го значения тоже самое, ток еще один цикл
11 jsmith82
 
30.04.15
08:02
12 jsmith82
 
30.04.15
08:07
(10) Не, я так предполагаю, там массив из массивов. То бишь тут циклом бесполезно
13 Vanyok
 
30.04.15
08:09
(9) Дело в том, что каждый раз разное количество массивов, думаю куча циклов тут не подойдёт.
(11) Маленько не то по ссылке
14 jsmith82
 
30.04.15
08:11
Функция рекурсивная должна быть. Ога
15 jsmith82
 
30.04.15
08:13
Решение-то нашёл. Только формализовывать  надо опять )
16 фобка
 
30.04.15
08:13
Двумерный массив это условно:
Мас1 = новый массив;
Мас2 = новый массив;
Мас1.добавить(мас2);
17 фобка
 
30.04.15
08:14
(13) нет, второй цикл будет " Для каждого Элт2 Из Элт1 Цикл"
18 Vanyok
 
30.04.15
08:16
(17) фобка, циклами не подойдёт, каждый раз может быть разное количество массивов
19 фобка
 
30.04.15
08:17
(14) рекурсия нужна если уровень вложенности неизвестен. А здесь конечное число - 3
20 jsmith82
 
30.04.15
08:18
Функция однозначно рекурсивная
В теле функции двойной цикл
21 Vanyok
 
30.04.15
08:37
(20) Одного будет не достаточно как в коде (0) ?
22 vde69
 
30.04.15
08:41
1 цикл по формированию текста и параметров запроса, потом один запрос с полным соеденением массивов первого уровня
23 jsmith82
 
30.04.15
08:42
Короче, ребята, как-то так по ходу, я думаю
24 jsmith82
 
30.04.15
08:42
Функция НайтиКомбинации(Массив, Сдвиг)
    
    Если Массив.Количество() = 1 Тогда
        
        ГлавныйМассив = Новый Массив();
        Для Каждого Эл Из Массив[0] Цикл
            ЛокМассив = Новый Массив();
            ЛокМассив.Добавить(Эл);
            ГлавныйМассив.Добавить(ЛокМассив);
        КонецЦикла;
        
        Возврат ГлавныйМассив;
        
    Иначе
        
        ГлавныйМассив = Новый Массив();
        
        Аргумент = Новый Массив();
        Для Итер = 1 По Массив.Количество() - 1 Цикл
            Аргумент.Добавить(Массив[Итер]);
        КонецЦикла;
        
        Правый = НайтиКомбинации(Аргумент);
        
        Для Каждого Эл0 Из Массив[0] Цикл
            
            Для Каждого Строка Из Правый Цикл
                
                ЛокМассив = Новый Массив();
                ЛокМассив.Добавить(Эл0);
                Для Каждого ЭлИзСтроки Из Строка Цикл                    
                    ЛокМассив.Добавить(ЭлИзСтроки);
                КонецЦикла;
                ГлавныйМассив.Добавить(ЛокМассив);
                
            КонецЦикла;
            
        КонецЦикла;
        
        Возврат ГлавныйМассив;
        
    КонецЕсли;
    
    
КонецФункции;
25 jsmith82
 
30.04.15
08:42
Ой, там второй аргумент Сдвиг убрать. Осталось просто
26 jsmith82
 
30.04.15
09:00
Усё работает
27 jsmith82
 
30.04.15
09:03
&НаКлиенте
Процедура Обойти(Команда)
    
    Двумерный = Новый Массив();
    Массив = Новый Массив();
    Массив.Добавить("1");
    Массив.Добавить("2");
    Массив.Добавить("3");
    Двумерный.Добавить(Массив);
    Массив = Новый Массив();
    Массив.Добавить("a");
    Массив.Добавить("b");
    Двумерный.Добавить(Массив);
    Массив = Новый Массив();
    Массив.Добавить("z");
    Двумерный.Добавить(Массив);
    
    Комбинации = НайтиКомбинации(Двумерный);
    МассивСтрок = ПолучитьСтроковоеПредставлениеКомбинаций(Комбинации);
    Для Каждого Эл Из МассивСтрок Цикл
        Сообщить(Эл);
    КонецЦикла;
    
КонецПроцедуры

Функция НайтиКомбинации(Массив)
    
    Если Массив.Количество() = 1 Тогда
        
        ГлавныйМассив = Новый Массив();
        Для Каждого Эл Из Массив[0] Цикл
            ЛокМассив = Новый Массив();
            ЛокМассив.Добавить(Эл);
            ГлавныйМассив.Добавить(ЛокМассив);
        КонецЦикла;
        
        Возврат ГлавныйМассив;
        
    Иначе
        
        ГлавныйМассив = Новый Массив();
        
        Аргумент = Новый Массив();
        Для Итер = 1 По Массив.Количество() - 1 Цикл
            Аргумент.Добавить(Массив[Итер]);
        КонецЦикла;
        
        Правый = НайтиКомбинации(Аргумент);
        
        Для Каждого Эл0 Из Массив[0] Цикл
            
            Для Каждого Строка Из Правый Цикл
                
                ЛокМассив = Новый Массив();
                ЛокМассив.Добавить(Эл0);
                Для Каждого ЭлИзСтроки Из Строка Цикл                    
                    ЛокМассив.Добавить(ЭлИзСтроки);
                КонецЦикла;
                ГлавныйМассив.Добавить(ЛокМассив);
                
            КонецЦикла;
            
        КонецЦикла;
        
        Возврат ГлавныйМассив;
        
    КонецЕсли;    
    
КонецФункции

Функция ПолучитьСтроковоеПредставлениеКомбинаций(Массив)
    
    МассивСтрок = Новый Массив();
    Для Каждого Строка Из Массив Цикл        
        Текст = "";
        Для Каждого Эл Из Строка Цикл
            Текст = Текст + Эл;
        КонецЦикла;
        МассивСтрок.Добавить(Текст);        
    КонецЦикла;
    Возврат МассивСтрок;
    
КонецФункции



1az
1bz
2az
2bz
3az
3bz
28 Vanyok
 
30.04.15
09:04
(26) Подтверждаю!
Огромное спасибо!
Белой завистью завидую))
29 Vanyok
 
30.04.15
09:07
(26) куда печеньки слать?)))
30 jsmith82
 
30.04.15
09:08
(29) А что, есть? )
31 Vanyok
 
30.04.15
09:17
(30) Пока нет))
Вдруг появятся))
32 ХардHard
 
30.04.15
09:31
Процедура КнопкаВыполнитьНажатие(Кнопка)
    МногоМерный = Новый Массив();
    
    Массив = Новый Массив();
    Массив.Добавить("1");
    Массив.Добавить("2");
    Массив.Добавить("3");
    МногоМерный.Добавить(Массив);
    
    Массив = Новый Массив();
    Массив.Добавить("a");
    Массив.Добавить("b");
    МногоМерный.Добавить(Массив);
    
    Массив = Новый Массив();
    Массив.Добавить("z");
    МногоМерный.Добавить(Массив);
  
    НовыйМассив  = Новый Массив;
    СтарыйМассив = Новый Массив;
    НомерИзмерения = 1;
    
    Для Каждого ОдномернМасс из МногоМерный Цикл
        СкопироватьМассив(СтарыйМассив,НовыйМассив);
        НовыйМассив.Очистить();
        Для Каждого ЭлемМасс из ОдномернМасс Цикл
            Если НомерИзмерения = 1 Тогда //первое измерение
                НовыйМассив.Добавить(ЭлемМасс);
            Иначе //все остальные измерения    
                Для Каждого ЭлИтоговогоМасс из СтарыйМассив Цикл
                    НовыйМассив.Добавить(ЭлИтоговогоМасс+ЭлемМасс);
                КонецЦикла;
            КонецЕсли;
        КонецЦикла;
        
        НомерИзмерения = НомерИзмерения + 1;
    КонецЦикла;
  
КонецПроцедуры

Процедура СкопироватьМассив(СтарыйМассив,НовыйМассив)
    СтарыйМассив.Очистить();
    Для Каждого ЭлМасс Из НовыйМассив Цикл
        СтарыйМассив.Добавить(ЭлМасс);
    КонецЦикла;
КонецПроцедуры
33 tznimble
 
30.04.15
14:03
Немного подытожу (для формализации):
На входе имеем никакой не двумерный массив, а банальное дерево. Причем, каждая ветвь содержит либо ветви, либо листья.
На выходе необходимо получить массив, содержащий комбинации всех листьев разных ветвей дерева.

Функция ПолучитьСочетания (Дерево)
// Дерево - массив массивов массивов массивов ... ;)
    ВыхМассив =Новый Массив;
    ОбработатьВетвь (Дерево, ВыхМассив);
    Возврат ВыхМассив;
КонецФункции

Процедура ОбработатьВевть (Ветвь, ВыхМассив)
    Если Ветвь.Количество()=0 тогда
        Возврат;
    КонецЕсли;
    
    Если ТипЗнч (Ветвь[0]) = Тип ("Массив") тогда
        Для каждого В из Ветвь цикл
            ОбработатьВетвь (В, ВыхМассив);
        КонецЦикла;
    Иначе
        Если ВыхМассив.Количество()=0 тогда
            Для Каждого Э из Ветвь цикл
                ВыхМассив.Добавить (Э);
            Конеццикла;
        Иначе
            врМассив = Новый Массив;
            Для каждого Э из Ветвь цикл
                Для каждого ЭЭ из ВыхМассив цикл
                    врМассив.Добавить (Сочесть(Э,ЭЭ));
                Конеццикла;
            Конеццикла;
            ВыхМассив = врМассив;
        КонецЕсли;
    КонецЕсли;
Конецпроцедуры

Функция Сочесть (Группа1, Группа2)
    Возврат Строка (Группа1) + Строка (Группа2);
КонецФункции