|
Сопоставить (сравнить) массивы | ☑ | ||
---|---|---|---|---|
0
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; КонецЦикла; |
|||
1
dmtrpv
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
|
Добавить оба массива в ТЗ и свернуть
|
|||
3
dmtrpv
15.09.16
✎
12:14
|
(2) Можно пример?
|
|||
4
dmtrpv
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 есть же во втором. |
|||
6
AceVi
15.09.16
✎
12:19
|
(4) Вот люди)
Свернуть - у таб знач есть метод. смотри хелп. |
|||
7
dmtrpv
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[СчЦ] Тогда ОниСовпадают = Ложь; Прервать; |
|||
10
dmtrpv
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 Тогда Сообщить(Строка.Значение); КонецЕсли; КонецЦикла; только это дохрена больше строк кода |
|||
18
dmtrpv
15.09.16
✎
12:42
|
(16) не подходит этот алгоритм. Потому что сравнение идет по индексам, первые не совпали, сразу идет Прервать. А надо, чтобы первый индекс первого массива искал совпадения по всем индексам второго массива, начиная с первого (ну то есть с нулевого) и если нет совпадения, индекс первого массива увеличивался на 1, а если есть совпадение, тогда эти индексы в поиске больше не участвуют.
|
|||
19
Лефмихалыч
15.09.16
✎
12:44
|
(18) окуеть у тебя проблема. Ну, заплати кому-нибудь, чтобы он убрал Прервать...
|
|||
20
Лефмихалыч
15.09.16
✎
12:45
|
поездец вообще! Готовый же код дал...
Я глубоко шокирован |
|||
21
ViSo76
15.09.16
✎
12:50
|
пПервыйМассив = Новый Массив;
пПервыйМассив.Добавить( 1 ); пПервыйМассив.Добавить( 2 ); пПервыйМассив.Добавить( 3 ); пПервыйМассив.Добавить( 3 ); пПервыйМассив.Добавить( 7 ); пВторойМассив = Новый Массив; пВторойМассив.Добавить( 1 ); пВторойМассив.Добавить( 2 ); пВторойМассив.Добавить( 2 ); пВторойМассив.Добавить( 3 ); пВторойМассив.Добавить( 4 ); пВторойМассив.Добавить( 5 ); пТаблицаОбъединения = Новый ТаблицаЗначений; пТаблицаОбъединения.Колонки.Добавить( "КолонкаЧисло", Новый ОписаниеТипов( "Число" ) ); пТаблицаОбъединения.Колонки.Добавить( "КолонкаИндекс", Новый ОписаниеТипов( "Число" ) ); пТаблицаОбъединения.Колонки.Добавить( "КолонкаСчетчик", Новый ОписаниеТипов( "Число" ) ); Для пИндекс = 0 По пПервыйМассив.Количество() - 1 Цикл пЗапись = пТаблицаОбъединения.Добавить(); пЗапись.КолонкаЧисло = пПервыйМассив[ пИндекс ]; пЗапись.КолонкаИндекс = пИндекс; пЗапись.КолонкаСчетчик = 1; КонецЦикла; Для пИндекс = 0 По пВторойМассив.Количество() - 1 Цикл пЗапись = пТаблицаОбъединения.Добавить(); пЗапись.КолонкаЧисло = пВторойМассив[ пИндекс ]; пЗапись.КолонкаИндекс = пИндекс; пЗапись.КолонкаСчетчик = 2; КонецЦикла; пТаблицаОбъединения.Свернуть( "КолонкаЧисло, КолонкаИндекс", "КолонкаСчетчик" ); Для Каждого пЗапись Из пТаблицаОбъединения.НайтиСтроки( Новый Структура( "КолонкаСчетчик", 1 ) ) Цикл Сообщить( "Индекс: " + пЗапись.КолонкаИндекс + " Число: " + пЗапись.КолонкаЧисло ); КонецЦикла; |
|||
22
dmtrpv
15.09.16
✎
12:58
|
(22) Близко, но тоже не то.
Так как ,если, например, Массив1 состоит из (1,2,3), а Массив2 состоит из (2,1,3), то эти массивы должны "совпадать", так как все элементы встречаются в обоих массивах, хоть и в разных индексах, а код (21) тут уже не справляется. |
|||
23
ViSo76
15.09.16
✎
13:01
|
(22) Тогда у тебя условие не правильное:
В первом массиве должны остаться только значениЕ 7. |
|||
24
ViSo76
15.09.16
✎
13:02
|
пПервыйМассив = Новый Массив;
пПервыйМассив.Добавить( 1 ); пПервыйМассив.Добавить( 2 ); пПервыйМассив.Добавить( 3 ); пПервыйМассив.Добавить( 3 ); пПервыйМассив.Добавить( 7 ); пВторойМассив = Новый Массив; пВторойМассив.Добавить( 1 ); пВторойМассив.Добавить( 2 ); пВторойМассив.Добавить( 2 ); пВторойМассив.Добавить( 3 ); пВторойМассив.Добавить( 4 ); пВторойМассив.Добавить( 5 ); пТаблицаОбъединения = Новый ТаблицаЗначений; пТаблицаОбъединения.Колонки.Добавить( "КолонкаЧисло", Новый ОписаниеТипов( "Число" ) ); пТаблицаОбъединения.Колонки.Добавить( "КолонкаСчетчик", Новый ОписаниеТипов( "Число" ) ); Для пИндекс = 0 По пПервыйМассив.Количество() - 1 Цикл пЗапись = пТаблицаОбъединения.Добавить(); пЗапись.КолонкаЧисло = пПервыйМассив[ пИндекс ]; пЗапись.КолонкаСчетчик = 1; КонецЦикла; Для пИндекс = 0 По пВторойМассив.Количество() - 1 Цикл пЗапись = пТаблицаОбъединения.Добавить(); пЗапись.КолонкаЧисло = пВторойМассив[ пИндекс ]; пЗапись.КолонкаСчетчик = 2; КонецЦикла; пТаблицаОбъединения.Свернуть( "КолонкаЧисло", "КолонкаСчетчик" ); Для Каждого пЗапись Из пТаблицаОбъединения.НайтиСтроки( Новый Структура( "КолонкаСчетчик", 1 ) ) Цикл Сообщить( "Число: " + пЗапись.КолонкаЧисло ); КонецЦикла; |
|||
25
dmtrpv
15.09.16
✎
13:11
|
(24) И значение 3 тоже должно остаться, так как во втором Массиве одна 3, а в первом две 3.
То есть 3 из первого массива совпала с 3 из второго массива. Теперь мы их не учитываем (или удаляем). В первом массиве осталась одна 3, а во втором теперь ее нет, также в первом массиве осталась 7, котором также нет во втором массиве. Итого результат "сравнения" должен быть 3 и 7. |
|||
26
Одинесю
15.09.16
✎
13:14
|
(25) А если в первом массиве две тройки? Две семерки?
|
|||
27
dmtrpv
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. |
|||
28
ViSo76
15.09.16
✎
13:39
|
пПервыйМассив = Новый Массив;
пПервыйМассив.Добавить( 1 ); пПервыйМассив.Добавить( 2 ); пПервыйМассив.Добавить( 3 ); пПервыйМассив.Добавить( 3 ); пПервыйМассив.Добавить( 7 ); пВторойМассив = Новый Массив; пВторойМассив.Добавить( 1 ); пВторойМассив.Добавить( 2 ); пВторойМассив.Добавить( 2 ); пВторойМассив.Добавить( 3 ); пВторойМассив.Добавить( 4 ); пВторойМассив.Добавить( 5 ); пСравнение = Новый Соответствие; Для пИндекс = 0 По пПервыйМассив.Количество() - 1 Цикл пЧисло = пПервыйМассив[ пИндекс ]; пЧислоКакСтрока = Строка( пЧисло ); пМассивИндексов = пСравнение[ пЧислоКакСтрока ]; Если пМассивИндексов = Неопределено Тогда пМассивИндексов = Новый Массив; пСравнение.Вставить( пЧислоКакСтрока, пМассивИндексов ); КонецЕсли; пМассивИндексов.Добавить( пИндекс ); КонецЦикла; Для Каждого пЧисло Из пВторойМассив Цикл пЧислоКакСтрока = Строка( пЧисло ); пМассивИндексов = пСравнение[ пЧислоКакСтрока ]; Если ЗначениеЗаполнено( пМассивИндексов ) Тогда пМассивИндексов.Удалить( 0 ); Если пМассивИндексов.Количество() = 0 Тогда пСравнение.Удалить( пЧислоКакСтрока ); КонецЕсли; КонецЕсли; КонецЦикла; Для Каждого пЗапись Из пСравнение Цикл Для Каждого пИндекс Из пЗапись.Значение Цикл Сообщить( "Число: " + Формат( пПервыйМассив[ пИндекс ], "ЧДЦ=0; ЧГ=" ) + " Индекс в массиве: " + Формат( пИндекс, "ЧДЦ=0; ЧГ=" ) ); КонецЦикла; КонецЦикла; |
|||
29
del123
15.09.16
✎
14:05
|
для каждого элемента из первого массива если найден такой элемент во втором массиве, удаляем оба, если нет, переходим к следующему элементу
|
|||
30
dmtrpv
15.09.16
✎
14:21
|
(30) Я понимаю. Но в этом случае, происходит сдвиг массивов по индексам на - 1, соответственно меняя размер массивов на - 1и очень сложно контролировать, чтобы текущие индексы обоих массивов при проверке на совпадение не выходили за границы обоих массивов. Поэтому и ищу готовый алгоритм. Я думал, что это что-то распространенное, математика же, но даже в сборниках алгоритмов ничего похожего не нашел.
|
|||
31
ViSo76
15.09.16
✎
14:24
|
(30) И что пример из (28) не подходит?
|
|||
32
dmtrpv
15.09.16
✎
14:27
|
(31) Спасибо.
Пока тестирую, пробуя заполнять массивы данными. Пока отрабатывает корректно. |
|||
33
Одинесю
15.09.16
✎
14:29
|
(30) В условии цикла у тебя типа Пока Количество() - 1 , замени 1 на переменную, при удалении элемента увеличивай ее на единицу
|
|||
34
FIXXXL
15.09.16
✎
14:29
|
суешь оба массива в ТЗ,
добавляешь колонку Колво и пишешь туда 1 сворачиваешь по колонке массивов и суммируешь по колонке Колво выбираешь строки у которых Колво<>2 |
|||
35
FIXXXL
15.09.16
✎
14:32
|
(34) а если подумать, то Цел(Колво)<>Колво/2
так будет универсально |
|||
36
dmtrpv
15.09.16
✎
14:33
|
(34) Можно ли реализовать циклами, без ТЗ?
|
|||
37
dmtrpv
15.09.16
✎
14:34
|
(36) Отменяю вопрос. В (28) циклами же
|
|||
38
dmtrpv
15.09.16
✎
14:35
|
(28) да, похоже то, что надо.
|
|||
39
del123
15.09.16
✎
14:36
|
(30) что проверять?
пускаешь цикл от нуля до количествомассива1 получаешь n-ый элемент первого массива поиск во втором массиве через найти(), если элемент найден, то удаляешь оба элемента (при это количествомассива1 уменьшается) и снова получаешь n-ый элемент массива, если элемент не найден то увеличиваешь n на 1 |
|||
40
del123
15.09.16
✎
14:37
|
(34) а если в первом массиве два одинаковых числа, а во втором массиве этих чисел нет?
|
|||
41
dmtrpv
15.09.16
✎
14:38
|
(40) Тогда эти два числа должны отобразиться в результате.
|
|||
42
dmtrpv
15.09.16
✎
14:39
|
(41) Ведь они не присутствуют во втором массиве, так что они считаются не найдены.
|
|||
43
FIXXXL
15.09.16
✎
14:39
|
(40) сам-на-сам еще сравнивать надо?
|
|||
44
Aistovich
15.09.16
✎
14:41
|
выгрузить в текст, сравнить размер в байтах
|
|||
45
Aistovich
15.09.16
✎
14:42
|
ой, их еще сопоставить надо
|
|||
46
Aistovich
15.09.16
✎
14:43
|
я бы строковое что-нибудь заиспользовал бы
|
|||
47
del123
15.09.16
✎
14:45
|
(41) Ну да, а способом из (34) так не получится
|
|||
48
Aistovich
15.09.16
✎
14:45
|
две строки сравнить да и всё
|
|||
49
dmtrpv
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 |
|||
50
dmtrpv
15.09.16
✎
14:48
|
Код из (28) вроде отрабатывает корректно, но хотелось бы что-нить....попроще что ли...
|
|||
51
ViSo76
15.09.16
✎
14:49
|
(50) :) Куда ещё проще
|
|||
52
dmtrpv
15.09.16
✎
14:50
|
(51) Спасибо за помощь
|
|||
53
FIXXXL
15.09.16
✎
14:52
|
(40) суй в ТЗ уникальные значения из обоих массивов
две ТЗ, обе свернуть, затем слить в одну, проставить Колво, свернуть и просуммировать найти строки с Цел(Колво)<>Колво/2 |
|||
54
arsik
гуру
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.ВыгрузитьЗначения(); |
|||
55
del123
15.09.16
✎
14:54
|
(54) ну я тоже самое и предлагал, только список значений имхо необязателен)
|
|||
56
arsik
гуру
15.09.16
✎
14:55
|
//Сори ошибка
НайденВСп2 = Сп2.НайтиПоЗначению(Сп1[Индекс]); //Вот так правильно НайденВСп2 = Сп2.НайтиПоЗначению(Сп1[Индекс].Значение); |
|||
57
del123
15.09.16
✎
14:55
|
(53) Опять же, а если в первой 4 одинаковых числа, а во второй ни одного?) На 4 делить потом?:)
|
|||
58
dmtrpv
15.09.16
✎
14:56
|
Вроде бы на первый взгляд простейшая математическая задача, а вот и нифига оказывается.
|
|||
59
arsik
гуру
15.09.16
✎
14:57
|
(55) А точно. Я что то не вспомнил, что в массиве искать можно
|
|||
60
del123
15.09.16
✎
14:58
|
(58) да простая, простая :)
|
|||
61
arsik
гуру
15.09.16
✎
15:00
|
Тогда вот так
//Код 1С м1 = Новый Массив; м2 = Новый Массив; Индекс = м1.Количество()-1; Пока Индекс >= 0 Цикл НайденВм2 = м2.Найти(м1[Индекс]); Если НайденВм2 <> Неопределено Тогда м2.Удалить(НайденВм2); м1.Удалить(Индекс); КонецЕсли; Индекс = Индекс-1; КонецЦикла; |
|||
62
dmtrpv
15.09.16
✎
15:06
|
(61) Да, тоже пойдет. Спасибо.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |