Что нового

Ускорение обработки массива

vovsla

Осваивающий
Сообщения
607
Репутация
36
Я не нашел примеров обработки многомерных массивов кроме как
Код:
Dim $testArr[3][3]=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Local $String
For $RowNum = 0 To UBound($testArr)-1
	For $ColNum = 0 To UBound($testArr, 2)-1
		$String&=$testArr[$RowNum][$ColNum]&', '
	Next
	$String=StringTrimRight($String, 2)
	ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $String = ' & $String & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
	$String=''
Next


Но при больших массивах такая операция занимает много времени, хотелось бы ее ускорить.
Например, каким-то образом, сделать шаблон колонок, и работать с ним.
Есть вот такая идея, только не понимаю как ее реализовать. Может кто-то подскажет...
Код:
Dim $testArr[3][3]=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
;~ Создание шаблона колонок
Local $String
For $ColNum = 0 To UBound($testArr, 2)-1
	$Row&='$testArr[$RowNum]['&$ColNum&'], '
Next
$String=StringTrimRight($String, 2)

;~ Вывод в консоль строки массива одной командой
For $RowNum = 0 To UBound($testArr)-1
	ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $String = $testArr['&$RowNum&'][$ColNum], $testArr['&$RowNum&'][$ColNum], $testArr['&$RowNum&'][$ColNum] ' & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
Next
 
A

Alofa

Гость
Код:
Local $sResult, $aArray[3000][3]

#Region --- Подготовительные действия ---
For $i = 0 To UBound($aArray) - 1 ; Забиваем массив данными для теста
	For $j = 0 To UBound($aArray, 2) - 1
		$aArray[$i][$j] = StringFormat("%04i", $i) & '-' & $j + 1
	Next
Next
#EndRegion --- Подготовительные действия ---

_Test(1)
_Test(2)

MsgBox(262144 + 64, 'Время выполнения функций:', $sResult)

Func _Test($i)
	Local $String, $sString_2, $hTimer
	$hTimer = TimerInit()
	Switch $i
		Case 1
			ConsoleWrite('++++++ _Test(' & $i & '):' & @CR)
			For $RowNum = 0 To UBound($aArray) - 1
				For $ColNum = 0 To UBound($aArray, 2) - 1
					$String &= $aArray[$RowNum][$ColNum] & ', '
				Next
				$String = StringTrimRight($String, 2)
				ConsoleWrite('Debug(' & @ScriptLineNumber & ') : $String = ' & $String & @CRLF & 'Error code: ' & @error & @CRLF)
				$String = ''
			Next
		Case 2
			For $RowNum = 0 To UBound($aArray) - 1
				For $ColNum = 0 To UBound($aArray, 2) - 1
					$String &= $aArray[$RowNum][$ColNum] & ', '
				Next
				$sString_2 &= 'Debug(' & @ScriptLineNumber & ') : $String = ' & StringTrimRight($String, 2) & @CRLF & 'Error code: ' & @error & @CRLF
				$String = ''
			Next
			ConsoleWrite('++++++ _Test(' & $i & '): ' & @CR & $sString_2)
	EndSwitch
	$sResult &= '_Test(' & $i & ') = ' & Round(TimerDiff($hTimer) / 1000, 4) & @CR
EndFunc   ;==>_Test
 
Автор
V

vovsla

Осваивающий
Сообщения
607
Репутация
36
Это не то, что нужно. Все равно получается цикл в цикле и общее кол-во циклов = "кол-во строк" Х "кол-во колонок".
А хотелось бы сделать так, чтобы кол-во циклов = "кол-во строк" + "кол-во колонок"
Функция составления строки для вставки в SQL занимает 23 секунды, а размер массива всего 6000 * 8

Код:
$YoBitInfoArr=GetYoBitInfo()

$TimeBegin=TimerInit()
$SIS=CASI('Info', 'ExchangeName, ServerTime, CurrencyPair, DecimalPlaces, MinPrice, MaxPrice, MinAmount, MinTotal, Hidden, Fee, FeeBuyer, FeeSeller', $YoBitInfoArr)
$TimeEnd=TimerDiff($TimeBegin)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $TimeEnd = ' & $TimeEnd & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console



Func GetYoBitInfo()
	$Info=GetInetData('https://yobit.net/api/3/info')
	If Not $Info Then Return False
	$InfoArr=StringRegExp($Info, ':?(".*?_.*?":\{".*?\},)', 3)
	$ServerTime=GetSREString($InfoArr[0], '"server_time":([0-9]*),')
	$InfoArr[0]=StringRegExpReplace($InfoArr[0], '.*?"pairs":\{', '')

	Dim $PairsTechInfo[UBound($InfoArr)][12]
	For $Num = 0 To UBound($InfoArr)-1
		$PairsTechInfo[$Num][0]='YObit'													;Название биржи
		$PairsTechInfo[$Num][1]=$ServerTime												;Время сервера
		$PairsTechInfo[$Num][2]=GetSREString($InfoArr[$Num], '"(.*?_.*?)":\{')			;Валютная пара
		$PairsTechInfo[$Num][3]=GetSREString($InfoArr[$Num], '"decimal_places":(.*?),')	;decimal_places: количество разрешенных знаков после запятой
		$PairsTechInfo[$Num][4]=GetSREString($InfoArr[$Num], '"min_price":(.*?),')		;min_price: минимальная разрешенная цена
		$PairsTechInfo[$Num][4]=StringReplace($PairsTechInfo[$Num][4], '.', ',')
		$PairsTechInfo[$Num][5]=GetSREString($InfoArr[$Num], '"max_price":(.*?),')		;max_price: максимальная разрешенная цена
		$PairsTechInfo[$Num][6]=GetSREString($InfoArr[$Num], '"min_amount":(.*?),')		;min_amount: минимальное разрешенное количество для покупки или продажи
		$PairsTechInfo[$Num][7]=GetSREString($InfoArr[$Num], '"min_total":(.*?),')
		$PairsTechInfo[$Num][8]=GetSREString($InfoArr[$Num], '"hidden":(.*?),')			;hidden: пара скрыта (0 или 1)
		$PairsTechInfo[$Num][9]=GetSREString($InfoArr[$Num], '"fee":(.*?),')
		$PairsTechInfo[$Num][10]=GetSREString($InfoArr[$Num], '"fee_buyer":(.*?),')
		$PairsTechInfo[$Num][11]=GetSREString($InfoArr[$Num], '"fee_seller":(.*?)\},')
	Next

	Return $PairsTechInfo
EndFunc

Func GetSREString($TestString, $SREPattern)
	$ResultArr=StringRegExp($TestString, $SREPattern, 1)
	If Not IsArray($ResultArr) Then Return '@error'
	Return $ResultArr[0]
EndFunc

Func GetInetData($Link)
	$Data=InetRead($Link)
	If @error Then Return False
	$DataString=BinaryToString($Data)
	If @error Then Return False
	Return $DataString
EndFunc

Func CASI($TableName, $Columns, $Array, $StartRow=0)
	If Not IsArray($Array) Then Return False

	$ColumnsArr=StringSplit($Columns, ',')
	If @error Then
		$ColumnsQuantity=1
	Else
		$ColumnsQuantity=$ColumnsArr[0]
	EndIf
	If $ColumnsQuantity<>UBound($Array, 2) Then Return False

	$SQLiteString="BEGIN;"
	If UBound($Array, 0)=1 Then
		For $ArrRowNum = $StartRow To UBound($Array)-1
			$Array[$ArrRowNum]=StringReplace($Array[$ArrRowNum], "'", "''")
			$SQLiteString&="INSERT INTO "&$TableName&" ("&$Columns&") VALUES ('"&$Array[$ArrRowNum]&"');"
		Next
	Else
		For $ArrRowNum = $StartRow To UBound($Array)-1
			$SQLiteString&="INSERT INTO "&$TableName&" ("&$Columns&") VALUES ("
			For $ArrColNum = 0 To UBound($Array, 2)-1
				$Array[$ArrRowNum][$ArrColNum]=StringReplace($Array[$ArrRowNum][$ArrColNum], "'", "''")
				$SQLiteString&="'"&$Array[$ArrRowNum][$ArrColNum]&"', "
			Next
			$SQLiteString=StringRegExpReplace($SQLiteString, ",\s\Z", ");")
		Next
	EndIf
	$SQLiteString&="COMMIT;"

	Return $SQLiteString
EndFunc


Можно в функции нагородить огород и сделать составление строки в зависимости от количества колонок в массиве, но хочется сделать нормальное решение, а не такое, которое будет выдавать сообщение о необходимости добавить поддержку большего количества колонок
Код:
$SQLiteString&="'"&$Array[$ArrRowNum][$ArrColNum]&"', "&"'"&$Array[$ArrRowNum][$ArrColNum]&"');" ; для двумерного
$SQLiteString&="'"&$Array[$ArrRowNum][$ArrColNum]&"', "&"'"&$Array[$ArrRowNum][$ArrColNum]&"', "&"'"&$Array[$ArrRowNum][$ArrColNum]&"');" ; для для трехмерного
 
A

Alofa

Гость
Vovsla сказал(а):
Это не то, что нужно...
Это был пример рациональной оптимизации вашего скрипта для увеличения скорости.

Vovsla сказал(а):
... кол-во циклов = "кол-во строк" + "кол-во колонок"...
Это как?
Допустим у вас есть массив 3 строки, по 3 колонки - вы хотите 6 циклов?

Vovsla сказал(а):
... Функция составления строки...
Ах вот оно как. Т.е. данные в массиве это всегда строки - это ключевой момент.
Значит измените форму хранения информации в массиве, это даст вам возможность переделать его в 1D.
В конечном случае можно вообще избавиться от него (массива), к примеру функция "GetYoBitInfo()" из второго вашего скрипта могла бы сразу делать Return строки.




Добавлено:
Сообщение автоматически объединено:

Vovsla сказал(а):
... в функции нагородить огород и сделать составление строки в зависимости от количества колонок в массиве, но хочется сделать нормальное решение...
В вашем случае это и есть нормальное решение. Ведь итог-то это все равно строка.
 
Автор
V

vovsla

Осваивающий
Сообщения
607
Репутация
36
В данном конкретном случае можно сделать 1D, но хочется предусмотреть и другие возможные ситуации.
В массиве 3 на 3, я предполагал делать 6 циклов следующим образом:
Сначала мы делаем шаблон для обработки строк массива, только я не понимаю как его сделать...
Код:
$Arr[3][3]

For $Num = 0 To UBound($Arr, 2)-1
	$(хитрый шаблон)&='текст_'&$Arr[][$Num]&'_текст'
Next


А дальше мы просто обрабатываем строку массива на всю глубину колонок массива.
Т.е. в (хитрый шаблон) добавляются только номера строк, которые нужно обработать, а номера колонок уже находятся в самом шаблоне.
Код:
$Arr[3][3]

For $Num = 0 To UBound($Arr)-1
	$String&=$(хитрый шаблон[$Num])
Next


Т.е. (хитрый шаблон) должен раскрываться как
'текст_'&$Arr[][0]&'_текст'&'текст_'&$Arr[][1]&'_текст'&'текст_'&$Arr[][2]&'_текст'

А при второй обработке в (хитрый шаблон) добавляются номера строк, и переменной $String присваивается строка
'текст_'&(содержимое $Arr[0][0])&'_текст'&'текст_'&(содержимое $Arr[0][1])&'_текст'&'текст_'&(содержимое $Arr[0][2])&'_текст'

Думаю, что в одну переменную нельзя запихнуть смесь переменных и текста, так что, по сути, вопрос можно поставить следующим образом.
Можно ли как-то раскрыть строку таким образом, чтобы ПК ее воспринял как смесь переменных и текста?
И запихнуть еще немного переменных в середину строки... )
 

ra4o

AutoIT Гуру
Сообщения
1,165
Репутация
247
Думаю, что в одну переменную нельзя запихнуть смесь переменных и текста
можете запихнуть всё , что угодно , используя, например разделители в строке, а потом выбирать нужный параметр при помощи, например регулярного выражения, только даст ли это прирост в скорости, ?
 
Верх