Перейти к основному содержимому

20.8. Как в QSP сравнить два массива?

>=5.9.4

Статья актуализирована для плееров версии 5.9.4, и данные решения не подойдут для более старых плееров. Если вы хотите знать, как сравнивались массивы до появления кортежей, ознакомьтесь с предыдущей версией статьи: Как в QSP 5.8.0 сравнить два массива?

В: Как в QSP сравнить два массива?

О: На первый взгляд вопрос кажется довольно простым, однако сравнение сравнению рознь. И если мы зададим вопрос: как именно мы хотим сравнить два массива? — возникают совершенно разные решения для различных вариантов сравнения.

Мы можем сравнить массивы по числу элементов:

if arrsize('mass_1') = arrsize('mass_2'):
*pl 'Число элементов в массивах одинаковое.'
else
*pl 'Число элементов в массивах разное.'
end

Довольно простая задача.

Возьмём задачу посложнее: проверить массивы на идентичность. То есть значение каждого элемента одного массива должно совпадать со значением элемента другого массива под тем же индексом:

! упаковывем содержимое сравниваемых массивов в кортежи
%array_1 = %ARRPACK('mass_1')
%array_2 = %ARRPACK('mass_2')

! сравниваем кортежи
if %array_1 = %array_2:
*pl 'Массивы идентичны.'
else
*pl 'Массивы не идентичны.'
end

Третья задача ещё сложнее. Нужно проверить, присутствуют ли в массивах одинаковые наборы значений, но при этом не важно, находятся ли элементы на одинаковых местах.

Например, вот такие два массива при сравнении должны показывать, что состоят из одинаковых наборов значений:

mass_1[0] = 1 & mass_2[0] = 4
mass_1[1] = 2 & mass_2[1] = 3
mass_1[2] = 3 & mass_2[2] = 2
mass_1[3] = 4 & mass_2[3] = 1

Решается такая задача тоже довольно просто:

! копируем содержимое сравниваемых массивов во временные массивы
local temp_mass_1, temp_mass_2
copyarr 'temp_mass_1', 'mass_1'
copyarr 'temp_mass_2', 'mass_2'

! сортируем содержимое временных массивов
sortarr 'temp_mass_1'
sortarr 'temp_mass_2'

! упаковываем временные массивы в кортежи
%array_1 = %arrpack('temp_mass_1')
%array_2 = %arrpack('temp_mass_2')

! и сравниваем эти кортежи
if %array_1 = %array_2:
*pl 'Массивы содержат одинаковые наборы элементов.'
else
*pl 'Массивы содержат разные наборы элементов.'
end

Данное решение адекватно обработает даже такое содержимое массивов:

mass_1[0] = 1 & mass_2[0] = 4
mass_1[1] = 1 & mass_2[1] = 4
mass_1[2] = 1 & mass_2[2] = 1
mass_1[3] = 4 & mass_2[3] = 1

Здесь в массивах содержатся одинаковые значения, но встречаются они разное количество раз. Т.е. наборы значений разные. При сравнении таких массивов последний алгоритм покажет, что массивы состоят из разных наборов элементов.

Самыми сложными случаями становятся различные варианты поиска пересечений массивов.

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

В этом случае нам нужно извлечь уникальные элементы из массивов во временные массивы, а затем сравнить временные массивы на содержание одинаковых наборов элементов:

local temp_mass_1, temp_mass_2

! получаем множества во временных массивах
loop local i =0 while i < arrsize('mass_1') step i+=1:
if arrpos('temp_mass_1', mass_1[i]) = -1:
temp_mass_1[] = mass_1[i]
end
end
loop local i =0 while i < arrsize('mass_2') step i+=1:
if arrpos('temp_mass_2', mass_2[i]) = -1:
temp_mass_2[] = mass_2[i]
end
end

! сортируем содержимое временных массивов
sortarr 'temp_mass_1'
sortarr 'temp_mass_2'

! упаковываем временные массивы в кортежи
%array_1 = %arrpack('temp_mass_1')
%array_2 = %arrpack('temp_mass_2')

! и сравниваем эти кортежи
if %array_1 = %array_2:
*pl 'Массивы содержат одинаковые множества элементов.'
else
*pl 'Массивы содержат разные множества элементов.'
end

Ещё один вариант поиска пересечений, это понять содержит ли второй массив хотя бы одно значение из первого массива. Это тоже делается с помощью цикла:

local $text_ = "В массивах нет общих значений."
loop local i = 0 while i < arrsize('mass_1') step i+=1:
if arrpos('mass_2', mass_1[i]) <> -1:
$text_ = "В массивах есть хотя бы один совпадающий элемент."
jump 'end_loop'
end
end
:end_loop
*pl $text_