Вход | Регистрация


1С:Предприятие :: 1С:Предприятие 8 общая

Сопоставить (сравнить) массивы

Сопоставить (сравнить) массивы
Я
   dmtrpv
 
15.09.16 - 12:09
Подскажите по алгоритму сопоставления двух массивов.

Есть 2 одномерных массива.
Бывает первый имеет больше значений, чем второй, бывает наоборот. Нужно сопоставить массивы, чтобы в одном из них, остались только те значения, которых нет во втором.
Например, МассивПервый(1,2,3,3,7); МассивВторой (1,2,2,3,4,5).
В первом массиве должны остаться только значения 3 и 7.

Вариант, который ниже не подходит, так как он удаляет в нужном массиве все совпадения, все зависимости сколько раз они встречаются, а мне так не надо.

Индекс1 = 0;    
Пока Индекс1 < Массив1Размер Цикл
        Индекс2 = 0;
        Пока Индекс2 < Всего2 Цикл
            Если Массив2[Индекс2] = Массив1[Индекс1] Тогда
                Массив2(Индекс2);
                Массив2Размер= Массив2Размер - 1;
            Иначе
                Индекс2 = Индекс2 + 1;
            КонецЕсли;
        КонецЦикла;
        Индекс1 = Индекс1 + 1;
    КонецЦикла;
 
 
   dmtrpv
 
1 - 15.09.16 - 12:10
Поправил
Индекс1 = 0;    
Пока Индекс1 < Массив1Размер Цикл
        Индекс2 = 0;
        Пока Индекс2 < Массив2Размер Цикл
            Если Массив2[Индекс2] = Массив1[Индекс1] Тогда
                Массив2(Индекс2);
                Массив2Размер= Массив2Размер - 1;
            Иначе
                Индекс2 = Индекс2 + 1;
            КонецЕсли;
        КонецЦикла;
        Индекс1 = Индекс1 + 1;
    КонецЦикла;
   Ёпрст
 
2 - 15.09.16 - 12:14
Добавить оба массива в ТЗ и свернуть
   dmtrpv
 
3 - 15.09.16 - 12:14
(2) Можно пример?
   dmtrpv
 
4 - 15.09.16 - 12:16
Я имею ввиду, как свернуть, а не добавить в ТЗ
   Одинесю
 
5 - 15.09.16 - 12:16
"Нужно сопоставить массивы, чтобы в одном из них, остались только те значения, которых нет во втором.
Например, МассивПервый(1,2,3,3,7); МассивВторой (1,2,2,3,4,5).
В первом массиве должны остаться только значения 3 и 7. "
3 есть же во втором.
   AceVi
 
6 - 15.09.16 - 12:19
(4) Вот люди)
Свернуть - у таб знач есть метод. смотри хелп.
   dmtrpv
 
7 - 15.09.16 - 12:20
(5) Да, 3 есть во втором массиве. А в первом массиве, две штуки 3, поэтому 3  и 7 должны остаться.
   Одинесю
 
8 - 15.09.16 - 12:21
Понятно, свернуть не пойдет, совпадение значений по индексу надо
   Лефмихалыч
 
9 - 15.09.16 - 12:23
(8)

Граница = Мин(Массив1.Количество(), Массив2.Количество());

ОниСовпадают = Истина;
Для СчЦ=0 по Граница-1 Цикл
   Если Массив1[СчЦ]<>Массив2[СчЦ] Тогда
      ОниСовпадают = Ложь;
      Прервать;
   dmtrpv
 
10 - 15.09.16 - 12:24
(8) Да, свернуть не подойдет. Есть пример алгоритма для такого сравнения? Я ничо не нашел. Какая то экзотика.
 
 Рекламное место пустует
   Лефмихалыч
 
11 - 15.09.16 - 12:25
>Например, МассивПервый(1,2,3,3,7); МассивВторой (1,2,2,3,4,5).
>В первом массиве должны остаться только значения 3 и 7.

почему в первом должно остаться 3 и 7, а не только 7?
   Одинесю
 
12 - 15.09.16 - 12:26
(8) + Определить мин индикса, сравнивать, преобразовывать. А вот вопрос - если в первом индекс больше - значения отсекаются или остаются.
   Одинесю
 
13 - 15.09.16 - 12:27
(11) Потому-что значение индекса 2 не совпадают
   Одинесю
 
14 - 15.09.16 - 12:27
(12) * индекса
   Лефмихалыч
 
15 - 15.09.16 - 12:29
(13) а, ну тогда в (11) заготовка. Там, где ОниСовпадают = Ложь; надо добавлять значения в третий массив, где будут храниться несовпадения
   Одинесю
 
16 - 15.09.16 - 12:32
(10) В (11) хорошо показано, в (15) сказано, что нужен третий массив, куда будут пихаться все несовпадения.
   Лефмихалыч
 
17 - 15.09.16 - 12:42
Свернуть, кажется, тоже можно, нужно просто уметь делить на два с остатком, ну и это будет

ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Значение");
ТЗ.Колонки.Добавить("Индекс");
ТЗ.Колонки.Добавить("Показатель");
Для СчЦ=0 по Массив1.Количество()-1 Цикл
   ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), Новый Структура("Значение, Индекс, Показатель", Массив1[СчЦ], СчЦ, 5));
КонецЦикла;
Для СчЦ=0 по Массив2.Количество()-1 Цикл
   ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), Новый Структура("Значение, Индекс, Показатель", Массив2[СчЦ], СчЦ, 7));
КонецЦикла;
ТЗ.Свернуть("Индекс, Значение", "Показатель");

Для каждого Строка из ТЗ Цикл
   Если Строка.Показатель%2=0 Тогда
      Сообщить(Строка.Значение);
   КонецЕсли;
КонецЦикла;



только это дохрена больше строк кода
   dmtrpv
 
18 - 15.09.16 - 12:42
(16) не подходит этот алгоритм. Потому что сравнение идет по индексам, первые не совпали, сразу идет Прервать. А надо, чтобы первый индекс первого массива искал совпадения по всем индексам второго массива, начиная с первого (ну то есть с нулевого) и если нет совпадения, индекс первого массива увеличивался на 1, а если есть совпадение, тогда эти индексы в поиске больше не участвуют.
   Лефмихалыч
 
19 - 15.09.16 - 12:44
(18) окуеть у тебя проблема. Ну, заплати кому-нибудь, чтобы он убрал Прервать...
   Лефмихалыч
 
20 - 15.09.16 - 12:45
поездец вообще! Готовый же код дал...






Я глубоко шокирован
   ViSo76
 
21 - 15.09.16 - 12:50
пПервыйМассив = Новый Массив;
пПервыйМассив.Добавить( 1 );
пПервыйМассив.Добавить( 2 );
пПервыйМассив.Добавить( 3 );
пПервыйМассив.Добавить( 3 );
пПервыйМассив.Добавить( 7 );

пВторойМассив = Новый Массив;
пВторойМассив.Добавить( 1 );
пВторойМассив.Добавить( 2 );
пВторойМассив.Добавить( 2 );
пВторойМассив.Добавить( 3 );
пВторойМассив.Добавить( 4 );
пВторойМассив.Добавить( 5 );

пТаблицаОбъединения = Новый ТаблицаЗначений;
пТаблицаОбъединения.Колонки.Добавить( "КолонкаЧисло", Новый ОписаниеТипов( "Число" ) );
пТаблицаОбъединения.Колонки.Добавить( "КолонкаИндекс", Новый ОписаниеТипов( "Число" ) );
пТаблицаОбъединения.Колонки.Добавить( "КолонкаСчетчик", Новый ОписаниеТипов( "Число" ) );

Для пИндекс = 0 По пПервыйМассив.Количество() - 1 Цикл

    пЗапись = пТаблицаОбъединения.Добавить();
    пЗапись.КолонкаЧисло = пПервыйМассив[ пИндекс ];
    пЗапись.КолонкаИндекс = пИндекс;
    пЗапись.КолонкаСчетчик = 1;

КонецЦикла;

Для пИндекс = 0 По пВторойМассив.Количество() - 1 Цикл

    пЗапись = пТаблицаОбъединения.Добавить();
    пЗапись.КолонкаЧисло = пВторойМассив[ пИндекс ];
    пЗапись.КолонкаИндекс = пИндекс;
    пЗапись.КолонкаСчетчик = 2;

КонецЦикла;

пТаблицаОбъединения.Свернуть( "КолонкаЧисло, КолонкаИндекс", "КолонкаСчетчик" );

Для Каждого пЗапись Из пТаблицаОбъединения.НайтиСтроки( Новый Структура( "КолонкаСчетчик", 1 ) ) Цикл

    Сообщить( "Индекс: " + пЗапись.КолонкаИндекс + " Число: " + пЗапись.КолонкаЧисло );

КонецЦикла;
   dmtrpv
 
22 - 15.09.16 - 12:58
(22) Близко, но тоже не то.
Так как ,если, например, Массив1 состоит из (1,2,3), а Массив2 состоит из (2,1,3), то эти массивы должны "совпадать", так как все элементы встречаются в обоих массивах, хоть и в разных индексах, а код (21) тут уже не справляется.
   ViSo76
 
23 - 15.09.16 - 13:01
(22) Тогда у тебя условие не правильное:

В первом массиве должны остаться только значениЕ 7.
   ViSo76
 
24 - 15.09.16 - 13:02
пПервыйМассив = Новый Массив;
пПервыйМассив.Добавить( 1 );
пПервыйМассив.Добавить( 2 );
пПервыйМассив.Добавить( 3 );
пПервыйМассив.Добавить( 3 );
пПервыйМассив.Добавить( 7 );

пВторойМассив = Новый Массив;
пВторойМассив.Добавить( 1 );
пВторойМассив.Добавить( 2 );
пВторойМассив.Добавить( 2 );
пВторойМассив.Добавить( 3 );
пВторойМассив.Добавить( 4 );
пВторойМассив.Добавить( 5 );

пТаблицаОбъединения = Новый ТаблицаЗначений;
пТаблицаОбъединения.Колонки.Добавить( "КолонкаЧисло", Новый ОписаниеТипов( "Число" ) );
пТаблицаОбъединения.Колонки.Добавить( "КолонкаСчетчик", Новый ОписаниеТипов( "Число" ) );

Для пИндекс = 0 По пПервыйМассив.Количество() - 1 Цикл

    пЗапись = пТаблицаОбъединения.Добавить();
    пЗапись.КолонкаЧисло = пПервыйМассив[ пИндекс ];
    пЗапись.КолонкаСчетчик = 1;

КонецЦикла;

Для пИндекс = 0 По пВторойМассив.Количество() - 1 Цикл

    пЗапись = пТаблицаОбъединения.Добавить();
    пЗапись.КолонкаЧисло = пВторойМассив[ пИндекс ];
    пЗапись.КолонкаСчетчик = 2;

КонецЦикла;

пТаблицаОбъединения.Свернуть( "КолонкаЧисло", "КолонкаСчетчик" );

Для Каждого пЗапись Из пТаблицаОбъединения.НайтиСтроки( Новый Структура( "КолонкаСчетчик", 1 ) ) Цикл

    Сообщить( "Число: " + пЗапись.КолонкаЧисло );

КонецЦикла;
   dmtrpv
 
25 - 15.09.16 - 13:11
(24) И значение 3 тоже должно остаться, так как во втором Массиве одна 3, а в первом две 3.
То есть 3 из первого массива совпала с 3 из второго массива. Теперь мы их не учитываем (или удаляем). В первом массиве осталась одна 3, а во втором теперь ее нет, также в первом массиве осталась 7, котором также нет во втором массиве. Итого результат "сравнения" должен быть 3 и 7.
   Одинесю
 
26 - 15.09.16 - 13:14
(25) А если в первом массиве две тройки? Две семерки?
   dmtrpv
 
27 - 15.09.16 - 13:23
(26) Если МассивПервый(1,2,3,3,7,7); МассивВторой (1,2,2,3,4,5).

Нам нужен рузультат для первого массива, он "главный".
Тогда результат сравнения: 3,7,7
Так как: в первом массиве по индексу 0 число 1, ищем его во всех индексах второго массива. Если находим, то эти индексы больше не используем (либо удаляем), если не находим, то переходим в следующему индексу первого массива.

Итого: так как во втором массиве присутствует все из первого, кроме 3,7,7.
   ViSo76
 
28 - 15.09.16 - 13:39
пПервыйМассив = Новый Массив;
пПервыйМассив.Добавить( 1 );
пПервыйМассив.Добавить( 2 );
пПервыйМассив.Добавить( 3 );
пПервыйМассив.Добавить( 3 );
пПервыйМассив.Добавить( 7 );

пВторойМассив = Новый Массив;
пВторойМассив.Добавить( 1 );
пВторойМассив.Добавить( 2 );
пВторойМассив.Добавить( 2 );
пВторойМассив.Добавить( 3 );
пВторойМассив.Добавить( 4 );
пВторойМассив.Добавить( 5 );

пСравнение = Новый Соответствие;

Для пИндекс = 0 По пПервыйМассив.Количество() - 1 Цикл

    пЧисло = пПервыйМассив[ пИндекс ];
    пЧислоКакСтрока = Строка( пЧисло );
    пМассивИндексов = пСравнение[ пЧислоКакСтрока ];

    Если пМассивИндексов = Неопределено Тогда

        пМассивИндексов = Новый Массив;
        пСравнение.Вставить( пЧислоКакСтрока, пМассивИндексов );

    КонецЕсли;

    пМассивИндексов.Добавить( пИндекс );

КонецЦикла;

Для Каждого пЧисло Из пВторойМассив Цикл

    пЧислоКакСтрока = Строка( пЧисло );
    пМассивИндексов = пСравнение[ пЧислоКакСтрока ];

    Если ЗначениеЗаполнено( пМассивИндексов ) Тогда

        пМассивИндексов.Удалить( 0 );

        Если пМассивИндексов.Количество() = 0 Тогда

            пСравнение.Удалить( пЧислоКакСтрока );

        КонецЕсли;

    КонецЕсли;

КонецЦикла;

Для Каждого пЗапись Из пСравнение Цикл
    
    Для Каждого пИндекс Из пЗапись.Значение Цикл

        Сообщить( "Число: " + Формат( пПервыйМассив[ пИндекс ], "ЧДЦ=0; ЧГ=" ) + " Индекс в массиве: " + Формат( пИндекс, "ЧДЦ=0; ЧГ=" ) );

    КонецЦикла;

КонецЦикла;
   del123
 
29 - 15.09.16 - 14:05
для каждого элемента из первого массива если найден такой элемент во втором массиве, удаляем оба, если нет, переходим к следующему элементу
   dmtrpv
 
30 - 15.09.16 - 14:21
(30) Я понимаю. Но в этом случае, происходит сдвиг массивов по индексам на - 1, соответственно меняя размер массивов на - 1и очень сложно контролировать, чтобы текущие индексы обоих массивов при проверке на совпадение не выходили за границы обоих массивов. Поэтому и ищу готовый алгоритм. Я думал, что это что-то распространенное, математика же, но даже в сборниках алгоритмов ничего похожего не нашел.
   ViSo76
 
31 - 15.09.16 - 14:24
(30) И что пример из (28) не подходит?
   dmtrpv
 
32 - 15.09.16 - 14:27
(31) Спасибо.
Пока тестирую, пробуя заполнять массивы данными.
Пока отрабатывает корректно.
   Одинесю
 
33 - 15.09.16 - 14:29
(30) В условии цикла у тебя типа Пока Количество() - 1 , замени 1 на переменную, при удалении элемента увеличивай ее на единицу
 
 
   FIXXXL
 
34 - 15.09.16 - 14:29
суешь оба массива в ТЗ, 
добавляешь колонку Колво и пишешь туда 1
сворачиваешь по колонке массивов и суммируешь по колонке Колво
выбираешь строки у которых Колво<>2
   FIXXXL
 
35 - 15.09.16 - 14:32
(34) а если подумать, то Цел(Колво)<>Колво/2

так будет универсально
   dmtrpv
 
36 - 15.09.16 - 14:33
(34) Можно ли реализовать циклами, без ТЗ?
   dmtrpv
 
37 - 15.09.16 - 14:34
(36) Отменяю вопрос. В (28) циклами же
   dmtrpv
 
38 - 15.09.16 - 14:35
(28) да, похоже то, что надо.
   del123
 
39 - 15.09.16 - 14:36
(30) что проверять?
пускаешь цикл от нуля до количествомассива1
получаешь n-ый элемент первого массива
поиск во втором массиве через найти(), если элемент найден, то удаляешь оба элемента (при это количествомассива1 уменьшается) и снова получаешь n-ый элемент массива, если элемент не найден то увеличиваешь n на 1
   del123
 
40 - 15.09.16 - 14:37
(34) а если в первом массиве два одинаковых числа, а во втором массиве этих чисел нет?
   dmtrpv
 
41 - 15.09.16 - 14:38
(40) Тогда эти два числа должны отобразиться в результате.
   dmtrpv
 
42 - 15.09.16 - 14:39
(41) Ведь они не присутствуют во втором массиве, так что они считаются не найдены.
   FIXXXL
 
43 - 15.09.16 - 14:39
(40) сам-на-сам еще сравнивать надо?
   Aistovich
 
44 - 15.09.16 - 14:41
выгрузить в текст, сравнить размер в байтах
   Aistovich
 
45 - 15.09.16 - 14:42
ой, их еще сопоставить надо
   Aistovich
 
46 - 15.09.16 - 14:43
я бы строковое что-нибудь заиспользовал бы
   del123
 
47 - 15.09.16 - 14:45
(41) Ну да, а способом из (34) так не получится
   Aistovich
 
48 - 15.09.16 - 14:45
две строки сравнить да и всё
   dmtrpv
 
49 - 15.09.16 - 14:46
Ну вот на пальцах.
Массив1(1,3,2,2)
Массив(2,1,3,4,5)

Результат сравнения:

число 1 из Массива 1 есть в Массив2, тогда вычеркиваем
число 3 из Массив1 есть в Массив2, тогда вычеркиваем
число 2 из Массив1 есть в Массив 2, тогда вычеркиваем
Число 2 тоже есть в Массив 2, но мы его вычеркнули выше, так что он считается как раз не найденным, он и есть результат!

Дальше можно не сравнивать, так как Массив1 закончился, хотя Массив 2 больше, но нам главнее Массив1.

Результат: только число 2
 
 Рекламное место пустует
   dmtrpv
 
50 - 15.09.16 - 14:48
Код из (28) вроде отрабатывает корректно, но хотелось бы что-нить....попроще что ли...
   ViSo76
 
51 - 15.09.16 - 14:49
(50) :) Куда ещё проще
   dmtrpv
 
52 - 15.09.16 - 14:50
(51) Спасибо за помощь
   FIXXXL
 
53 - 15.09.16 - 14:52
(40) суй в ТЗ уникальные значения из обоих массивов
две ТЗ, обе свернуть, затем слить в одну, 
проставить Колво, свернуть и просуммировать
найти строки с Цел(Колво)<>Колво/2
   arsik
 
54 - 15.09.16 - 14:53
(0) Может через списокзначений проще сделать?

//Код 1С


м1 = Новый Массив;
м2 = Новый Массив;

Сп1 = Новый СписокЗначений;
Сп2 = Новый СписокЗначений;

Сп1.ЗагрузитьЗначения(м1);
Сп2.ЗагрузитьЗначения(м2);

Индекс = Сп1.Количество()-1;
Пока Индекс >= 0 Цикл
    НайденВСп2 = Сп2.НайтиПоЗначению(Сп1[Индекс]);
    Если НайденВСп2 <> Неопределено Тогда
        Сп2.Удалить(НайденВСп2);
        Сп1.Удалить(Индекс);
    КонецЕсли;
    Индекс = Индекс-1;
КонецЦикла;

м1 = Сп1.ВыгрузитьЗначения();
   del123
 
55 - 15.09.16 - 14:54
(54) ну я тоже самое и предлагал, только список значений имхо необязателен)
   arsik
 
56 - 15.09.16 - 14:55
//Сори ошибка


НайденВСп2 = Сп2.НайтиПоЗначению(Сп1[Индекс]);

//Вот так правильно


НайденВСп2 = Сп2.НайтиПоЗначению(Сп1[Индекс].Значение);
   del123
 
57 - 15.09.16 - 14:55
(53) Опять же, а если в первой 4 одинаковых числа, а во второй ни одного?) На 4 делить потом?:)
   dmtrpv
 
58 - 15.09.16 - 14:56
Вроде бы на первый взгляд простейшая математическая задача, а вот и нифига оказывается.
   arsik
 
59 - 15.09.16 - 14:57
(55) А точно. Я что то не вспомнил, что в массиве искать можно
   del123
 
60 - 15.09.16 - 14:58
(58) да простая, простая :)
   arsik
 
61 - 15.09.16 - 15:00
Тогда вот так
//Код 1С


м1 = Новый Массив;
м2 = Новый Массив;

Индекс = м1.Количество()-1;
Пока Индекс >= 0 Цикл
    НайденВм2 = м2.Найти(м1[Индекс]);
    Если НайденВм2 <> Неопределено Тогда
        м2.Удалить(НайденВм2);
        м1.Удалить(Индекс);
    КонецЕсли;
    Индекс = Индекс-1;
КонецЦикла;
   dmtrpv
 
62 - 15.09.16 - 15:06
(61) Да, тоже пойдет. Спасибо.


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует