Что нового

[Массивы] Объединение двух 2d массивов в один по условию.

inx

Знающий
Сообщения
43
Репутация
12
Есть два массива, нужно их соединить в один по условию:
В результат добавляется $i "строчка" из первого массива, затем из второго добавляются все "строки" для которых $aArray1[$i][3] = $aArray2[$k][3]
Если совпадений нет, то ничего ни из первого, ни из второго массивов не пишется в результат.
(В итоге должны быть "строки" из разных массивов, но с одинаковыми элементами в определенной "колонке")

array1.xlsx
Код:
Заголовок 1	Заголовок 2	Заголовок 3	Столбец - условие	Заголовок 4
_10001	_Название_01	_Количество_01	5	_Еще_данные_01
_10002	_Название_02	_Количество_02	12	_Еще_данные_02
_10003	_Название_03	_Количество_03	28	_Еще_данные_03
_10004	_Название_04	_Количество_04	7	_Еще_данные_04
array2.xlsx
Код:
Заголовок 1	Заголовок 2	Заголовок 3	Столбец - условие	Заголовок 4
10005	Название_05	Количество_05	12	Еще_данные_05
10006	Название_06	Количество_06	5	Еще_данные_06
10007	Название_07	Количество_07	12	Еще_данные_07
10005	Название_05	Количество_05	28	Еще_данные_05
10006	Название_06	Количество_06	6	Еще_данные_06
10007	Название_07	Количество_07	54	Еще_данные_07
10008	Название_08	Количество_08	12	Еще_данные_08
10009	Название_09	Количество_09	9	Еще_данные_09
10010	Название_10	Количество_10	5	Еще_данные_10

В результате должно получится такое:
Код:
Заголовок 1	Заголовок 2	Заголовок 3	Столбец - условие	Заголовок 4
_10001	_Название_01	_Количество_01	5	_Еще_данные_01
10006	Название_06	Количество_06	5	Еще_данные_06
10010	Название_10	Количество_10	5	Еще_данные_10
_10002	_Название_02	_Количество_02	12	_Еще_данные_02
10005	Название_05	Количество_05	12	Еще_данные_05
10007	Название_07	Количество_07	12	Еще_данные_07
10008	Название_08	Количество_08	12	Еще_данные_08
_10003	_Название_03	_Количество_03	28	_Еще_данные_03
10005	Название_05	Количество_05	28	Еще_данные_05

Но результат работы скрипта немного другой:
Код:
Заголовок 1	Заголовок 2	Заголовок 3	Столбец - условие	Заголовок 4
_10001	_Название_01	_Количество_01	5	_Еще_данные_01
10006	Название_06	Количество_06	5	Еще_данные_06
10010	Название_10	Количество_10	5	Еще_данные_10
_10002	_Название_02	_Количество_02	12	_Еще_данные_02
10005	Название_05	Количество_05	12	Еще_данные_05
10007	Название_07	Количество_07	12	Еще_данные_07
10008	Название_08	Количество_08	12	Еще_данные_08
_10003	_Название_03	_Количество_03	28	_Еще_данные_03
10005	Название_05	Количество_05	28	Еще_данные_05
_10004	_Название_04	_Количество_04	7	_Еще_данные_04


Делаю так:
Код:
#include <Excel.au3>
#include <Array.au3>

Local $sFile1 = @ScriptDir & "\array1.xlsx" ; что ищем
Local $sFile2 = @ScriptDir & "\array2.xlsx" ; в чем
Local $oExcel_1 = _ExcelBookOpen($sFile1, 0)
Local $oExcel_2 = _ExcelBookOpen($sFile2, 0)

Global $aArray1 = _ExcelReadSheetToArray($oExcel_1, 1, 1, 0, 0, 1)
_ExcelBookClose($oExcel_1)
DelRowsWithEmptyElementInCol($aArray1, 2) ; первую "строку" удалим
_ArrayDisplay($aArray1, "$aArray1")

Global $aArray2 = _ExcelReadSheetToArray($oExcel_2, 1, 1, 0, 0, 1)
_ExcelBookClose($oExcel_2)
DelRowsWithEmptyElementInCol($aArray2, 2)
_ArrayDisplay($aArray2, "$aArray2")

Combine()

Func Combine()
	Local $aArrayResult[2][5]
	$aArrayResult[0][0] = "Заголовок 1"
	$aArrayResult[0][1] = "Заголовок 2"
	$aArrayResult[0][2] = "Заголовок 3"
	$aArrayResult[0][3] = "Столбец - условие"
	$aArrayResult[0][4] = "Заголовок 4"
	Local $ResultCurrentRow = 1
	Local $something = 1
	For $i = 1 To UBound($aArray1, 1) - 1 Step 1 ; заголовок не обрабатываем
		If $something = 1 Then
			$aArrayResult[$ResultCurrentRow][0] = $aArray1[$i][0] ; Заголовок 1 -"код"
			$aArrayResult[$ResultCurrentRow][1] = $aArray1[$i][1] ; Заголовок 2 - "название"
			$aArrayResult[$ResultCurrentRow][2] = $aArray1[$i][2] ; Заголовок 3 - "количество"
			$aArrayResult[$ResultCurrentRow][3] = $aArray1[$i][3] ; Столбец-условие
			$aArrayResult[$ResultCurrentRow][4] = $aArray1[$i][4] ; Заголовок 4
			$ResultCurrentRow = $ResultCurrentRow + 1
			ReDim $aArrayResult[$ResultCurrentRow + 1][5]
			$something = 0
		EndIf
		For $k = 1 To UBound($aArray2, 1) - 1 Step 1 ; заголовок не обрабатываем
			If Number($aArray1[$i][3]) = Number($aArray2[$k][3]) Then
				$aArrayResult[$ResultCurrentRow][0] = $aArray2[$k][0] ; Заголовок 1 -"код"
				$aArrayResult[$ResultCurrentRow][1] = $aArray2[$k][1] ; Заголовок 2 - "название"
				$aArrayResult[$ResultCurrentRow][2] = $aArray2[$k][2] ; Заголовок 3 - "количество"
				$aArrayResult[$ResultCurrentRow][3] = $aArray2[$k][3] ; Столбец-условие
				$aArrayResult[$ResultCurrentRow][4] = $aArray2[$k][4] ; Заголовок 4
				$ResultCurrentRow = $ResultCurrentRow + 1
				ReDim $aArrayResult[$ResultCurrentRow + 1][5]
				$something = 1
			EndIf
		Next
	Next
	_ArrayDisplay($aArrayResult, "$aArrayResult")
EndFunc   ;==>Combine

Func DelRowsWithEmptyElementInCol(ByRef $array, $col)
	Local $vEmpty = True
	For $i = UBound($array) - 1 To 0 Step -1
		If StringCompare($array[$i][$col], "", 0) <> 0 Then
			$vEmpty = False
		EndIf
		If $vEmpty = True Then _ArrayDelete($array, $i)
		$vEmpty = True
	Next
	Return $array
EndFunc   ;==>DelRowsWithEmptyElementInCol


Вопросы:

Как убрать лишнюю последнюю пустую строку из результата?
Как не добавлять в результат последнюю* строчку из $aArray1? (в случае отсутствия совпадений из второго массива)
(*или первую - если в array1.xlsx поменять первую и последнюю строки местами)

Как все это можно сделать проще?

Будет ли быстрее(медленнее/сложнее) просто слить два массива в один, отсортировать по "столбец-условие", затем определить по нему же "уникальные" (элемент "выше"/"ниже" <> текущему) строки и удалить их?
 

beliy

Продвинутый
Сообщения
372
Репутация
72
Возможный вариант решения:

Код:
#include <Excel.au3>
#include <Array.au3>

Local $sFile1 = @ScriptDir & "\array1.xlsx" ; что ищем
Local $sFile2 = @ScriptDir & "\array2.xlsx" ; в чем
Local $oExcel_1 = _ExcelBookOpen($sFile1, 0)
Local $oExcel_2 = _ExcelBookOpen($sFile2, 0)

Local $aArrayData1 = _ExcelReadSheetToArray($oExcel_1, 1, 1, 0, 0, 1)
_ExcelBookClose($oExcel_1)
DelRowsWithEmptyElementInCol($aArrayData1, 2) ; первую "строку" удалим
_ArrayDisplay($aArrayData1, "$aArrayData1")

Local $aArrayData2 = _ExcelReadSheetToArray($oExcel_2, 1, 1, 0, 0, 1)
_ExcelBookClose($oExcel_2)
DelRowsWithEmptyElementInCol($aArrayData2, 2)
_ArrayDisplay($aArrayData2, "$aArrayData2")

$endArray = Combine($aArrayData1, $aArrayData2, 'Заголовок 1', 0, 0 )
_ArrayDisplay($endArray, "$endArray")

Func Combine($aArray1, $aArray2, $sCheckHeader, $sCheckHeaderRows, $sCheckHeaderCols )
   Local $iRows1 = UBound($aArray1, 1)
   Local $iCols1 =  UBound($aArray1, 2)
   Local $iRows2 = UBound($aArray2, 1)
   Local $aArrayResult[2][$iCols1]
   Local $ResultCurrentRow = 0
   Local $addFirstArray = true
   Local $addHeader= true

   For $i = 0 To $iRows1 - 1
	  For $k = 0 To $iRows2 - 1
		 If (Number($aArray1[$i][3]) = Number($aArray2[$k][3])) And (Number($aArray1[$i][0]) = Not Number($aArray2[$k][0])) Then
			IF $addFirstArray Then
			   ReDim $aArrayResult[$ResultCurrentRow + 2][$iCols1]
			   For $n = 0 To $iCols1 - 1
				  $aArrayResult[$ResultCurrentRow][$n] = $aArray1[$i][$n]
			   Next
			   $ResultCurrentRow += 1

			   For $n = 0 To $iCols1 - 1
				  $aArrayResult[$ResultCurrentRow][$n] = $aArray2[$k][$n]
			   Next
			   $ResultCurrentRow += 1

			   $addFirstArray = false
			Else
			   ReDim $aArrayResult[$ResultCurrentRow + 1][$iCols1]
			   For $n = 0 To $iCols1 - 1
				  $aArrayResult[$ResultCurrentRow][$n] = $aArray2[$k][$n]
			   Next
			   $ResultCurrentRow += 1
			EndIF
		 ElseIf ( $addHeader and ($aArray1[$sCheckHeaderRows][$sCheckHeaderCols] = $sCheckHeader)) Then
			   ReDim $aArrayResult[$ResultCurrentRow + 1][$iCols1]
			   For $n = 0 To $iCols1 - 1
				  $aArrayResult[$ResultCurrentRow][$n] = $aArray2[$i][$n]
			   Next
			   $ResultCurrentRow += 1
			   $addHeader = Not $addHeader
		 Else
			@error = -1
		 EndIf
	  Next
	  $addFirstArray = true
   Next

    return $aArrayResult
EndFunc   ;==>Combine

Func DelRowsWithEmptyElementInCol(ByRef $array, $col)
    Local $vEmpty = True
    For $i = UBound($array) - 1 To 0 Step -1
        If StringCompare($array[$i][$col], "", 0) <> 0 Then
            $vEmpty = False
        EndIf
        If $vEmpty = True Then _ArrayDelete($array, $i)
        $vEmpty = True
    Next
    Return $array
EndFunc   ;==>DelRowsWithEmptyElementInCol
 
Верх