Что нового

[Массивы] Как сравнить два массива и показать отличающиеся элементы?

Tapok

Новичок
Сообщения
204
Репутация
0
Есть ли функция для сравнения двух массивов (с возможностью вывода элементов одного массива, которых нет в другом)?

Кажется, то что надо, получится если использовать две функции:

Код:
_ArrayConcatenate

и
Код:
_ArrayUnique


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

InnI

AutoIT Гуру
Сообщения
4,927
Репутация
1,434
Tapok
функция для сравнения двух массивов
Код:
#include <Array.au3>

Global $aArray1[] = [0,1,3,4,5]
Global $aArray2[] = [1,3,4,6,7]

_ArrayDisplay(_ArrayCompare($aArray1, $aArray2))
_ArrayDisplay(_ArrayCompare($aArray2, $aArray1))

Func _ArrayCompare(Const ByRef $a1, Const ByRef $a2)
  If Not IsArray($a1) Or Not IsArray($a2) Then Return
  If UBound($a1, 0) <> 1 Or UBound($a2, 0) <> 1 Then Return
  Local $sUniq = ""
  For $i = 0 To UBound($a1) - 1
    For $j = 0 To UBound($a2) - 1
      If $a1[$i] = $a2[$j] Then ExitLoop
    Next
    If $j = UBound($a2) Then $sUniq &= $a1[$i] & "|"
  Next
  Return StringSplit(StringTrimRight($sUniq, 1), "|", 2)
EndFunc
 
Автор
T

Tapok

Новичок
Сообщения
204
Репутация
0
Inni, спасибо большое, то, что надо! :smile:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
InnI,
А если хотя бы один из массивов, например, двумерный? :smile:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
InnI,
А теперь первая строка функции не нужна. :smile:
 

InnI

AutoIT Гуру
Сообщения
4,927
Репутация
1,434
должно сравнивать двумерные массивы?
Нет, одномерные.
Двумерные здесь:
 

Norm

Продвинутый
Сообщения
289
Репутация
74
Понадобилась такая функция, но нужно было сравнить значения в столбцах в определёных строках.
Решил сделать универсальную функцию, которая сравнивает значения как 1D так и 2D по колонкам или строкам.
По умолчанию все значения сравниваются как строки и опционально как числа.
Код:
#include <Array.au3>
Local $Array1[2][12] = [[0,0,0,0,0,0,0,0,0,0,0,0],["TA",1,3,5,17,6,7,8,9,10,11,"MG"]]
Local $Array2[10][2] = [[1,0], [2,0], [2,0], [3,0], [4,0], [5,0], [6,0], [8,0], [10,0], ["MG",0]]
Local $aExRet = _ArrayCompare($Array1, $Array2, 0, 1, 2, 0, 0, 1, 0, 1)
_ArrayDisplay($aExRet)

Dim $Array1[14] = [1,"ZU",3,5,17,6,7,8,"GH",10,11,12]
Dim $Array2[12][2] = [[0,1], [0,1], [0,3], [0,5], [0,17], [0,6], [0,7], [0,"GH"], [0,9], [0,10], [0,11], [0,12]]
Local $aExRet = _ArrayCompare($Array1, $Array2, 0, 0, 1, 0, 1, 1, 0, 1)
_ArrayDisplay($aExRet)


Func _ArrayCompare(Const ByRef $Array1, _ ; Array1 для сравнения
  Const ByRef $Array2, _ ; $Array2 для сопоставления
  $iStr1 = 0, _ ; Начальный индекс для Array1
  $i1rc = 0, _; Парам. для $Array1; Столбец 1 или 2D Array1 // Строка 2D, если $iRg1 = 2
  $iRg1 = 1, _ ; Парам. для массива1; только 1 или 2; При значении 1 вы ищете во всех строках, при значении 2 — во всех столбцах.
  $iStr2 = 0, _ ; Начальный индекс для $Array2
  $i2rc = 0, _; Парам. для $Array2; Столбец 1 или 2D Array2 // Строка 2D, если $iRg1 = 2
  $iRg2 = 1, _ ; Парам. для $Array2; только 1 или 2; При 1 поиск осуществляется во всех строках, при 2 – во всех столбцах.
  $iDig = 0, _; 0 => все значения сравниваются как строка; если 1 как числа
  $iRtS = 1) ; 1 => двумерный массив с результатом для столбцов [x][0]-$Array1, [x][1]-$Array1 и [x][2] со всеми присутствующими в обоих массивах
  ; ^^^^^ if 0 => без столбца [x][2] со всеми существующими в обоих массивах
    If Not IsArray($Array1) Or Not IsArray($Array2) Then Return SetError(-1)

    If ($iRg1 > 2) Or ($iRg1 < 1) Then Return SetError(-3)

    If ($iRg2 > 2) Or ($iRg2 < 1) Then Return SetError(-4)

    Local $iDmsA = UBound($Array1, 0)
    Local $iDmsB = UBound($Array2, 0)
    If ($iRg1 = 2 And $iDmsA = 1) Or ($iRg2 = 2 And $iDmsB = 1) Then Return SetError(-5)

    Local $nUb1 = UBound($Array1, $iRg1)
    Local $nUb2 = UBound($Array2, $iRg2)
    Local $oDic1 = ObjCreate("Scripting.Dictionary")
    Local $oDic2 = ObjCreate("Scripting.Dictionary")
    Local $oDic3 = ObjCreate("Scripting.Dictionary")
   For $iN = $iStr1 To $nUb1 -1
        If $iDmsA = 1 Then
            $Array1[$iN] = ($iDig ? (Number($Array1[$iN])) : (String($Array1[$iN])))
            $oDic1.Item($Array1[$iN])
        Else
            If $iRg1 = 1 Then
                $Array1[$iN][$i1rc] = ($iDig ? (Number($Array1[$iN][$i1rc])) : (String($Array1[$iN][$i1rc])))
                $oDic1.Item($Array1[$iN][$i1rc])
            Else
                $Array1[$i1rc][$iN] = ($iDig ? (Number($Array1[$i1rc][$iN])) : (String($Array1[$i1rc][$iN])))
                $oDic1.Item($Array1[$i1rc][$iN])
            EndIf
        EndIf
    Next
    For $iN = $iStr2 To $nUb2 -1
        If $iDmsB = 1 Then
            $oDic2.Item($iDig ? (Number($Array2[$iN])) : (String($Array2[$iN])))
        Else
            If $iRg2 = 1 Then
                $oDic2.Item($iDig ? (Number($Array2[$iN][$i2rc])) : (String($Array2[$iN][$i2rc])))
            Else
                $oDic2.Item($iDig ? (Number($Array2[$i2rc][$iN])) : (String($Array2[$i2rc][$iN])))
            EndIf
        EndIf
    Next
    For $iN = $iStr1 To $nUb1 -1
        If $iDmsA = 1 Then
            If $oDic2.Exists($Array1[$iN]) Then
                $oDic3.Item($Array1[$iN])
            EndIf
        Else
            If $iRg1 = 1 Then
                If $oDic2.Exists($Array1[$iN][$i1rc]) Then
                    $oDic3.Item($Array1[$iN][$i1rc])
                EndIf
            Else
                If $oDic2.Exists($Array1[$i1rc][$iN]) Then
                    $oDic3.Item($Array1[$i1rc][$iN])
                EndIf
            EndIf
        EndIf
    Next
    Local $aRet3 = $oDic3.Keys()
    Local $nUb3 = UBound($aRet3)-1
    For $iN = 0 To $nUb3
        If $oDic1.Exists($aRet3[$iN]) Then
            $oDic1.Remove($aRet3[$iN])
        EndIf
        If $oDic2.Exists($aRet3[$iN]) Then
            $oDic2.Remove($aRet3[$iN])
        EndIf
    Next
    $oDic3.RemoveAll()

    Local $aRet1 = $oDic1.Keys()
    $nUb1 = UBound($aRet1)-1
    $oDic1.RemoveAll()
    Local $aRet2 = $oDic2.Keys()
    $nUb2 = UBound($aRet2)-1
    $oDic2.RemoveAll()
    If Not $iRtS Then
        $nUb3 = -1
    EndIf
    Local $nExUB = (($nUb1 > $nUb2) ? (($nUb1 > $nUb3) ? $nUb1 : $nUb3) : (($nUb2 > $nUb3) ? $nUb2 : $nUb3))
    Local $aExRet[$nExUB+1][($iRtS ? 3 : 2)]
    For $iN = 0 To $nExUB
        If $iN <= $nUb1 Then
            $aExRet[$iN][0] = $aRet1[$iN]
        EndIf
        If $iN <= $nUb2 Then
            $aExRet[$iN][1] = $aRet2[$iN]
        EndIf
        If $iN <= $nUb3 Then
            $aExRet[$iN][2] = $aRet3[$iN]
        EndIf
    Next
    Return $aExRet
EndFunc
 
Последнее редактирование:
Верх