Что нового

Массив. Запись массива. Сравнение массивов

CrazyDoc

Новичок
Сообщения
75
Репутация
2
Пожалуйста, подскажите решения которые будут работать лучше, чем примененные. скрипт:
Код:
#include <Array.au3>
#include <Excel.au3>
#include <Date.au3>
#include <File.au3>
Local $oWorkbook, $oAppl, $Array1, $Array2, $Array3, $a, $b, $c, $d, $aTemp1, $aTemp2, $aTemp3
$iDateCalc = _DateDiff( 's',"1970/01/01 00:00:00",_NowCalc())
$oAppl=_Excel_Open()
$oWorkbook=_Excel_BookAttach("TwsDde.xls","filename")
While 1
	_FileReadToArray(@ScriptDir & "\Trades.txt", $Array1)
	_FileReadToArray(@ScriptDir & "\Ticket_work_short.txt", $Array2)
	For $a=1 To $Array1[0]
		$d=False
		$aTemp1=StringSplit($Array1[$a],";",2)
		For $b=1 To $Array2[0]
			$aTemp2=StringSplit($Array2[$b],";",2)
			If StringInStr($Array2[$b],$aTemp1[0],0,1,1,10) Then
				$d=True
				ExitLoop
			EndIf
		Next
		if ($d=False) And ($aTemp1[2]=1) And ($aTemp1[4]>=$iDateCalc) Then
			$hFile=FileOpen(@ScriptDir&"\Ticket_work_short.txt",1)
			FileWriteLine($hFile,$Array1[$a])
			FileClose($hFile)
			_FileReadToArray(@ScriptDir & "\MT4_TWS.txt", $Array3)
			For $c=1 To $Array3[0]
				$aTemp3=StringSplit($Array3[$c],";",2)
				if $aTemp1[1]==$aTemp3[0] Then
					$Symbol=$aTemp3[1]
					$Type=$aTemp3[2]
					$Exchange=$aTemp3[3]
					$Currency=$aTemp3[4]
					Local $RanIns=_Excel_RangeInsert($oWorkbook.Activesheet,"11:11",$xlShiftDown)
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Symbol,"A11")
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Type,"B11")
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Exchange,"H11")
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Currency,"J11")
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"SELL","M11")
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"1","N11")
					Local $ExcRanWr=_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"MKT","O11")
					$oAppl.Activesheet.Cells(11,1).Select
					$oAppl.Run("Sheet2.placeOrder")
				EndIf
			Next
		EndIf
	Next
	Sleep(100)
WEnd
Данный скрипт парсит файл со строками(который несколько раз в секунду обновляется, какие-то строки удаляются, какие-то добавляются) и если находит новую строку - обрабатывает ее(заменяет символы в строке и отправляет все это добро на исполнение макросу excel'я). На мой взгляд, надо убрать чтение файла Ticket_Work_Short(он является списком обработанных строк и применяется для сравнения) - а массив построенный на его основе, создавать в теле скрипта(тем самым избежав чтения с диска). Пока не придумал как это сделать.

Здесь буду обновлять конечный результат со всеми поправками:
Код:
#include <Array.au3>
#include <Excel.au3>
#include <Date.au3>
#include <File.au3>
Local $dic, $iDateCalc, $oAppl, $oWorkbook, $Array3, $Array1, $a, $aTemp1, $c, $aTemp3, $Symbol, $Type, $Exchange, $Currency, $Array
$dic = ObjCreate('scripting.dictionary')
$iDateCalc = _DateDiff( 's',"1970/01/01 00:00:00",_NowCalc())
$oAppl=_Excel_Open()
$oWorkbook=_Excel_BookAttach("TwsDde.xls","filename")
_FileReadToArray(@ScriptDir & "\MT4_TWS.txt", $Array3)
While 1
	_FileReadToArray(@ScriptDir & "\Trades.txt", $Array1)
	For $a=1 To $Array1[0]
		If $dic.exists($Array1[$a]) Then
			ContinueLoop
		Else
			$dic.add($Array1[$a], 0)
			$aTemp1=StringSplit($Array1[$a],";",2)
			if $aTemp1[2]=1  Then
				For $c=1 To $Array3[0]
					$aTemp3=StringSplit($Array3[$c],";",2)
					if $aTemp1[1]==$aTemp3[0] And ($aTemp1[4]>=$iDateCalc) Then
						$Symbol=$aTemp3[1]
						$Type=$aTemp3[2]
						$Exchange=$aTemp3[3]
						$Currency=$aTemp3[4]
						_Excel_RangeInsert($oWorkbook.Activesheet,"11:11",$xlShiftDown)
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Symbol,"A11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Type,"B11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Exchange,"H11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Currency,"J11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"SELL","M11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"1","N11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"MKT","O11")
						$oAppl.Activesheet.Cells(11,1).Select
						$oAppl.Run("Sheet2.placeOrder")
					EndIf
				Next
			EndIf
		EndIf
	Next
WEnd

Здесь полезные ссылки:
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Можно воспользоваться словарем scripting.dictionary для хранения обработанных строк.
А строки между собой можно сравнивать без разделения на ; целиком? Если что то в строке поменялось, значит затем ее можно поподробнее посмотреть..
MT4_TWS.txt если этот файл не меняется то можно его прочитать до начала цикла while
Если длинна строки до разделителя ; фиксирована то можно не использовать StringSplit , а сразу пользоваться StringInStr($Array2[$b],$aTemp1[0],0,1,1,вот тут длина), тут вижу что вы так и делаете.
Трудно что то советовать. Может ли сам макрос заниматься этим делом? Он может читать файлы? Макрос отработает намного быстрее.
Формат файла разделенный ; - неудобный
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2
inververs сказал(а):
Можно воспользоваться словарем scripting.dictionary для хранения обработанных строк.
Нашел описание:Scripting.Dictionary. Читаю.
inververs сказал(а):
А строки между собой можно сравнивать без разделения на ; целиком?
Да, можно. Главное чтобы во втором массиве сохранялось упоминание что строка из первого массива уже обработана(в строке из первого массива уникален только первый блок - 9цифр)
inververs сказал(а):
MT4_TWS.txt если этот файл не меняется то можно его прочитать до начала цикла while
Не меняется. Сделано.
inververs сказал(а):
Если длинна строки до разделителя ; фиксирована то можно не использовать StringSplit
Но ведь затем все равно придется разбить строку, для замены символов в ней - подходящих для макроса Excel.
inververs сказал(а):
Может ли сам макрос заниматься этим делом? Он может читать файлы? Макрос отработает намного быстрее.
Это макрос написанный на VisualBasic - обрабатывает данные в полях Excel'я и отсылает их программе. API Excel для TWS. В VB скорее всего я не разберусь и за пару месяцев, поэтому был выбран этот вариант.
inververs сказал(а):
Формат файла разделенный ; - неудобный
Это можно поменять. Какой будет удобнее? Почему?

Пока что искал возможности по записи второго массива в виде строки и поиску по ней при помощи StringInStr(). Стоит ли вообще пробовать? Строка в итоге ведь может получиться очень длинной...
(Попробовал сделать вот так:
Код:
#include <File.au3>
Local $Array="0;0;0;0;0;", $Array1, $a
_FileReadToArray(@ScriptDir & "\Trades.txt", $Array1)
For $a=1 To $Array1[0]
	If Not(StringInStr($Array,$Array1[$a])) Then $Array&=$Array1[$a]
Next
MsgBox(0,$a,$Array)
вроде работает. Это вообще правильный метод добавления символов к строке? Пойду проверять - как быстро с этим будет работать StringInStr().)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
По словарю вот вся документация: https://msdn.microsoft.com/en-us/library/x4k5wbx4%28v=vs.84%29.aspx
http://autoit-script.ru/autoit3_docs/tutorials/Scripting.Dictionary.htm
Пример:
Код:
;Создадим словарь
Local $dic = ObjCreate('scripting.dictionary')
ConsoleWrite(ObjName($dic) & @CRLF)
;Занесем в словарь пару строк. Вместо ключей будем использовать всю строку, вместо значений 0
$dic.add('test;string;blablabla', 0)
$dic.add('hello;this;is:a;data', 0)
;Проверим существует ли строка test;string;blablabla в словаре
If $dic.exists('test;string;blablabla') Then
	ConsoleWrite('Существует' & @CRLF)
Else
	ConsoleWrite('- Не существует' & @CRLF)
EndIf


Я бы посоветовал все данные(Trades.txt) сразу выгружать в базу данных. Можно хранить колонку id, время последнего изменения строки, разбить все колонки по полям. И тогда любые измененные или добавленные строки можно доставать запросами. И все операции с массивами, циклами, словарями не нужны будут. Но ты тут сам решай, сможешь ли ты вместо Trades.txt записывать данные в базу.

CrazyDoc [?]
Пока что искал возможности по записи второго массива в виде строки и поиску по ней при помощи StringInStr(). Стоит ли вообще пробовать? Строка в итоге ведь может получиться очень длинной...
На сколько я помню перебор массива будет быстрее чем StringInStr
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2
inververs сказал(а):
сможешь ли ты вместо Trades.txt записывать данные в базу.
На данный момент не смогу(( поэтому:
1. пока что сделал так:
Код:
#include <Array.au3>
#include <Excel.au3>
#include <Date.au3>
#include <File.au3>
Local $dic, $iDateCalc, $oAppl, $oWorkbook, $Array3, $Array1, $a, $aTemp1, $c, $aTemp3, $Symbol, $Type, $Exchange, $Currency, $Array
$dic = ObjCreate('scripting.dictionary')
$iDateCalc = _DateDiff( 's',"1970/01/01 00:00:00",_NowCalc())
$oAppl=_Excel_Open()
$oWorkbook=_Excel_BookAttach("TwsDde.xls","filename")
_FileReadToArray(@ScriptDir & "\MT4_TWS.txt", $Array3)
While 1
	_FileReadToArray(@ScriptDir & "\Trades.txt", $Array1)
	For $a=1 To $Array1[0]
		If $dic.exists($Array1[$a]) Then
			ContinueLoop
		Else
			$dic.add($Array1[$a], 0)
			$aTemp1=StringSplit($Array1[$a],";",2)
			if $aTemp1[2]=1  Then
				For $c=1 To $Array3[0]
					$aTemp3=StringSplit($Array3[$c],";",2)
					if $aTemp1[1]==$aTemp3[0] And ($aTemp1[4]>=$iDateCalc) Then
						$Symbol=$aTemp3[1]
						$Type=$aTemp3[2]
						$Exchange=$aTemp3[3]
						$Currency=$aTemp3[4]
						_Excel_RangeInsert($oWorkbook.Activesheet,"11:11",$xlShiftDown)
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Symbol,"A11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Type,"B11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Exchange,"H11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,$Currency,"J11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"SELL","M11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"1","N11")
						_Excel_RangeWrite($oWorkbook,$oWorkbook.Activesheet,"MKT","O11")
						$oAppl.Activesheet.Cells(11,1).Select
						$oAppl.Run("Sheet2.placeOrder")
					EndIf
				Next
			EndIf
		EndIf
	Next
WEnd
2. ушел читать про SQL.
3. тему отмечу решенной

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

edyapd

Осваивающий
Сообщения
380
Репутация
30
inververs сказал(а):
На сколько я помню перебор массива будет быстрее чем StringInStr
Вы про это?
Код:
Dim $a1[10000]

For $i = 0 To UBound($a1)-2
	$a1[$i] = "Нет"
Next
$a1[UBound($a1)-1] = "Да"

$s1 = ""
For $i = 0 To UBound($a1)-2
	$s1 = $s1 & "Нет"
Next
$s1 = $s1 & "Да"

$hTimer = TimerInit()
For $i=0 To UBound($a1)-1
	If $a1[$i] = "Да" Then 
		ConsoleWrite("Найдено искомое в массиве за " & TimerDiff($hTimer)/1000 & @LF)
		ExitLoop
	EndIf
Next
$hTimer = TimerInit()
If StringInStr($s1, "Да") Then ConsoleWrite("Найдено искомое в строке за " & TimerDiff($hTimer)/1000 & @LF)
 
Верх