1

Тема: AHK: Сравнение массива с массивом

У меня есть два массива.
Мне нужно узнать совпадают ли они.


if array1=array2 				; не работает
	MsgBox 1
if array1=%array2% 				; ложное срабатывание
	MsgBox 2
if array1=% array2 				; ложное срабатывание
	MsgBox 3
if array1[]=array2[] 			; ложное срабатывание
	MsgBox 4
if Array.array1=Array.array2 	; ложное срабатывание
	MsgBox 5

Уже не знаю что делать.

2

Re: AHK: Сравнение массива с массивом

a := ["123", "123", "123", "222"]
b := ["123", "123", "123", "222", "222"]

func(arr1, arr2) {
	if (arr1.MaxIndex() = arr2.MaxIndex()) {
		Loop % arr1.MaxIndex() {
			if (arr1[A_Index] = arr2[A_Index]) {
				continue
			} else {
				return, false
			}
		}
		return, true
	} else {
		return, false
	}
}

msgbox, % func(a, b)

Просто фантазия .

Когда вы говорите что не можете сделать, вам всего-лишь не хватает фантазии придумать какой-нибудь костыль.

3 (изменено: serzh82saratov, 2017-11-06 01:05:03)

Re: AHK: Сравнение массива с массивом

Можно перевести массив в строку, или лучше в хеш сумму, и их сравнивать.


a := ["123", "123", "123", "222"]
b := ["123", "123", "123", "222"]

MsgBox % ObjToBase64(a) = ObjToBase64(b)

ObjToBase64(obj) {
	If !IsObject(obj)
		Return
	VarSetCapacity(Bin, Size := RawObjectSize(obj, 0) + 8, 0)
    RawObject(obj, NumPut(Size - 8, 0 + (addr := &Bin), "Int64"), 0)
	DllCall("Crypt32.dll\CryptBinaryToString"  
		, Ptr, addr, UInt, Size, UInt, 0x00000001|0x40000000, UInt, 0, UIntP, TChars, "CDECL Int")
	VarSetCapacity(Base64, Req := TChars * (A_IsUnicode ? 2 : 1 ))
	DllCall("Crypt32.dll\CryptBinaryToString"  
		, Ptr, addr, UInt, Size, UInt, 0x00000001|0x40000000, Str, Base64, UIntP, Req, "CDECL Int")
	Return Base64
}

RawObject(obj, addr, buf := 0, objects := 0) {
	; Type.Enum:    Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
	; Negative for keys and positive for values
	if !objects
		objects:={(""):0,(obj):0}
	else objects[obj]:=(++objects[""])
	for k,v in obj
	{ ; 9 = Int64 for size and Char for type
		If IsObject(k){
			If objects.HasKey(k)
				NumPut(-12,addr+0,"Char"),NumPut(objects[k],addr+1,"Int64"),addr+=9
			else NumPut(-11,addr+0,"Char"),NumPut(sz:=RawObjectSize(k,buf),addr+1,"Int64"),RawObject(k,addr+9,buf,objects),addr+=sz+9
		}else if (k+0="")
			NumPut(-10,addr+0,"Char"),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,"Int64"),addr+=sz+9
		else NumPut( InStr(k,".")?-9:k>4294967295?-8:k>65535?-6:k>255?-4:k>-1?-2:k>-129?-1:k>-32769?-3:k>-2147483649?-5:-7,addr+0,"Char")
			,NumPut(k,addr+1,InStr(k,".")?"Double":k>4294967295?"UInt64":k>65535?"UInt":k>255?"UShort":k>-1?"UChar":k>-129?"Char":k>-32769?"Short":k>-2147483649?"Int":"Int64")
			,addr+=InStr(k,".")||k>4294967295?9:k>65535?5:k>255?3:k>-129?2:k>-32769?3:k>-2147483649?5:9
		If IsObject(v){
			if objects.HasKey(v)
				NumPut( 12,addr+0,"Char"),NumPut(objects[v],addr+1,"Int64"),addr+=9
			else NumPut( 11,addr+0,"Char"),NumPut(sz:=RawObjectSize(v,buf),addr+1,"Int64"),RawObject(v,addr+9,buf,objects),addr+=sz+9
			}else if (v+0="")
		NumPut( 10,addr+0,"Char"),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,"Int64"),DllCall("RtlMoveMemory","PTR",addr+9,"PTR",buf?obj.GetAddress(k):&v,"PTR",sz),addr+=sz+9
		else NumPut(InStr(v,".")?9:v>4294967295?8:v>65535?6:v>255?4:v>-1?2:v>-129?1:v>-32769?3:v>-2147483649?5:7,addr+0,"Char")
			,NumPut(v,addr+1,InStr(v,".")?"Double":v>4294967295?"UInt64":v>65535?"UInt":v>255?"UShort":v>-1?"UChar":v>-129?"Char":v>-32769?"Short":v>-2147483649?"Int":"Int64")
			,addr+=InStr(v,".")||v>4294967295?9:v>65535?5:v>255?3:v>-129?2:v>-32769?3:v>-2147483649?5:9
	}
}

RawObjectSize(obj,buf:=0,objects:=0){
	if !objects
		objects:={(obj):1}
	else if !objects.HasKey(obj)
		objects[obj]:=1
	for k,v in obj
	{
		If IsObject(k)
			sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
		else if (k+0="")
			sz+=StrPut(k)*2+9
		else sz+=InStr(k,".")||k>4294967295?9:k>65535?5:k>255?3:k>-129?2:k>-32769?3:k>-2147483649?5:9
		If IsObject(v)
			sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
		else if (v+0="")
			sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
		else sz+=InStr(v,".")||v>4294967295?9:v>65535?5:v>255?3:v>-129?2:v>-32769?3:v>-2147483649?5:9
	}
	return sz
}

С хэшем:


a := ["123", "123", "123", "222"]
b := ["123", "123", "123", "222"]

MsgBox % ObjToMD5Hash(a) = ObjToMD5Hash(b)

ObjToMD5Hash(obj) {
	If !IsObject(obj)
		Return
	VarSetCapacity(Bin, Size := RawObjectSize(obj, 0) + 8, 0)
    RawObject(obj, NumPut(Size - 8, 0 + (addr := &Bin), "Int64"), 0)
	Return CalcMD5Hash(addr, Size)
}

RawObject(obj, addr, buf := 0, objects := 0) {
	; Type.Enum:    Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
	; Negative for keys and positive for values
	if !objects
		objects:={(""):0,(obj):0}
	else objects[obj]:=(++objects[""])
	for k,v in obj
	{ ; 9 = Int64 for size and Char for type
		If IsObject(k){
			If objects.HasKey(k)
				NumPut(-12,addr+0,"Char"),NumPut(objects[k],addr+1,"Int64"),addr+=9
			else NumPut(-11,addr+0,"Char"),NumPut(sz:=RawObjectSize(k,buf),addr+1,"Int64"),RawObject(k,addr+9,buf,objects),addr+=sz+9
		}else if (k+0="")
			NumPut(-10,addr+0,"Char"),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,"Int64"),addr+=sz+9
		else NumPut( InStr(k,".")?-9:k>4294967295?-8:k>65535?-6:k>255?-4:k>-1?-2:k>-129?-1:k>-32769?-3:k>-2147483649?-5:-7,addr+0,"Char")
			,NumPut(k,addr+1,InStr(k,".")?"Double":k>4294967295?"UInt64":k>65535?"UInt":k>255?"UShort":k>-1?"UChar":k>-129?"Char":k>-32769?"Short":k>-2147483649?"Int":"Int64")
			,addr+=InStr(k,".")||k>4294967295?9:k>65535?5:k>255?3:k>-129?2:k>-32769?3:k>-2147483649?5:9
		If IsObject(v){
			if objects.HasKey(v)
				NumPut( 12,addr+0,"Char"),NumPut(objects[v],addr+1,"Int64"),addr+=9
			else NumPut( 11,addr+0,"Char"),NumPut(sz:=RawObjectSize(v,buf),addr+1,"Int64"),RawObject(v,addr+9,buf,objects),addr+=sz+9
			}else if (v+0="")
		NumPut( 10,addr+0,"Char"),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,"Int64"),DllCall("RtlMoveMemory","PTR",addr+9,"PTR",buf?obj.GetAddress(k):&v,"PTR",sz),addr+=sz+9
		else NumPut(InStr(v,".")?9:v>4294967295?8:v>65535?6:v>255?4:v>-1?2:v>-129?1:v>-32769?3:v>-2147483649?5:7,addr+0,"Char")
			,NumPut(v,addr+1,InStr(v,".")?"Double":v>4294967295?"UInt64":v>65535?"UInt":v>255?"UShort":v>-1?"UChar":v>-129?"Char":v>-32769?"Short":v>-2147483649?"Int":"Int64")
			,addr+=InStr(v,".")||v>4294967295?9:v>65535?5:v>255?3:v>-129?2:v>-32769?3:v>-2147483649?5:9
	}
}

RawObjectSize(obj,buf:=0,objects:=0){
	if !objects
		objects:={(obj):1}
	else if !objects.HasKey(obj)
		objects[obj]:=1
	for k,v in obj
	{
		If IsObject(k)
			sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
		else if (k+0="")
			sz+=StrPut(k)*2+9
		else sz+=InStr(k,".")||k>4294967295?9:k>65535?5:k>255?3:k>-129?2:k>-32769?3:k>-2147483649?5:9
		If IsObject(v)
			sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
		else if (v+0="")
			sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
		else sz+=InStr(v,".")||v>4294967295?9:v>65535?5:v>255?3:v>-129?2:v>-32769?3:v>-2147483649?5:9
	}
	return sz
}

CalcMD5Hash(addr, length) {
	Static PROV_RSA_AES := 24, CRYPT_VERIFYCONTEXT := 0xF0000000, HP_HASHVAL := 0x0002, hash := 0, hashlength := 0, hProv := 1
	if (DllCall("advapi32\CryptAcquireContext", PtrP, hProv, Ptr, 0, Ptr, 0, UInt, PROV_RSA_AES, UInt, CRYPT_VERIFYCONTEXT))
		if (DllCall("advapi32\CryptCreateHash", Ptr, hProv, UInt, 32771, UInt, 0, UInt, 0, "Ptr*", hHash))  ;	CALG_MD5 := 32771
			if (DllCall("advapi32\CryptHashData", Ptr, hHash, Ptr, addr, UInt, length, UInt, 0))
				if (DllCall("advapi32\CryptGetHashParam", Ptr, hHash, UInt, HP_HASHVAL, Ptr, 0, UIntP, hashlength, UInt, 0)) {
					VarSetCapacity(hash, hashlength, 0)
					if (DllCall("advapi32\CryptGetHashParam", Ptr, hHash, UInt, HP_HASHVAL, Ptr, &hash, UIntP, hashlength, UInt, 0))
						Loop % hashlength
							hashstr .= Format("{:02X}", *(&hash + A_Index - 1))
				}
	DllCall("advapi32\CryptDestroyHash", Ptr, hHash), DllCall("advapi32\CryptReleaseContext", Ptr, hProv, UInt, 0)
	Return hashstr
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

4

Re: AHK: Сравнение массива с массивом

serzh82saratov
Можно подробнее?
Что за строка?
Что за хеш сумма?
Чем второе лучше первого? 
Разве не будет проще просто перебрать члены массива в две переменные и сравнить их?
Либо сделать как предложил belyankin12?

Да и вообще, от AHK я ожидал встроенной функции.

5 (изменено: belyankin12, 2017-11-06 19:07:01)

Re: AHK: Сравнение массива с массивом

Ну если бы она была serzh бы её точно привел, он гораздо опытнее меня. Я таких функций не знаю, потому сделал свою. В плане эффективности работы все же вариант serzh'a лучше, работает быстрее в том случае, если количество ключей в массивах одинаковое, если же нет, то мой быстрее выдаст отрицательный результат (но речь идёт о 5-10 мс времени, потому не суть). А вот если массив будет огромным, то мой вариант будет гораздо медленнее, но, мой вариант самый простой в плане исполнения: базовые функции, образовавшие костыль - его проще понять. Выбирайте. Кстати, в строку лучше массив не переводить: у строк есть ограничение по длине, а потому можно рано или поздно упереться в него.

И да:

Разве не будет проще просто перебрать члены массива в две переменные и сравнить их?
Либо сделать как предложил belyankin12?

Я как раз это и предложил.

Когда вы говорите что не можете сделать, вам всего-лишь не хватает фантазии придумать какой-нибудь костыль.

6

Re: AHK: Сравнение массива с массивом

belyankin12 пишет:

у строк есть ограничение по длине

Нет, ограничение это если прописывать переменную в файле скрипта, если её "создавать" то нет. А, в случае с хэшем, строки будут просто кроче, и сравнивать их "проще".

shahlik002 пишет:

Разве не будет проще просто перебрать члены массива в две переменные и сравнить их?

Проще, если массивы простые, а если ассоциативные и вложенные, то простой способ надо бы доработать.

shahlik002 пишет:

Можно подробнее?

Любой массив переводится в бинарные данные, они в строку Base64 или более короткую хеш сумму этих данных, и далее сравниваются между собой как две строки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

7 (изменено: serzh82saratov, 2017-11-14 22:43:15)

Re: AHK: Сравнение массива с массивом

Кстати, не уверен, но вроде как строки можно не сравнивать, а можно сравнивать данные.


a := ["123","222"]
b := ["123","222"]

MsgBox % ObjToData(a) = ObjToData(b)

ObjToData(obj) {
	If !IsObject(obj)
		Return
	VarSetCapacity(Bin, Size := RawObjectSize(obj, 0) + 8, 0)
    RawObject(obj, NumPut(Size - 8, 0 + (&Bin), "Int64"), 0)
	Return Bin
}

RawObject(obj, addr, buf := 0, objects := 0) {
	; Type.Enum:    Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
	; Negative for keys and positive for values
	if !objects
		objects:={(""):0,(obj):0}
	else objects[obj]:=(++objects[""])
	for k,v in obj
	{ ; 9 = Int64 for size and Char for type
		If IsObject(k){
			If objects.HasKey(k)
				NumPut(-12,addr+0,"Char"),NumPut(objects[k],addr+1,"Int64"),addr+=9
			else NumPut(-11,addr+0,"Char"),NumPut(sz:=RawObjectSize(k,buf),addr+1,"Int64"),RawObject(k,addr+9,buf,objects),addr+=sz+9
		}else if (k+0="")
			NumPut(-10,addr+0,"Char"),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,"Int64"),addr+=sz+9
		else NumPut( InStr(k,".")?-9:k>4294967295?-8:k>65535?-6:k>255?-4:k>-1?-2:k>-129?-1:k>-32769?-3:k>-2147483649?-5:-7,addr+0,"Char")
			,NumPut(k,addr+1,InStr(k,".")?"Double":k>4294967295?"UInt64":k>65535?"UInt":k>255?"UShort":k>-1?"UChar":k>-129?"Char":k>-32769?"Short":k>-2147483649?"Int":"Int64")
			,addr+=InStr(k,".")||k>4294967295?9:k>65535?5:k>255?3:k>-129?2:k>-32769?3:k>-2147483649?5:9
		If IsObject(v){
			if objects.HasKey(v)
				NumPut( 12,addr+0,"Char"),NumPut(objects[v],addr+1,"Int64"),addr+=9
			else NumPut( 11,addr+0,"Char"),NumPut(sz:=RawObjectSize(v,buf),addr+1,"Int64"),RawObject(v,addr+9,buf,objects),addr+=sz+9
			}else if (v+0="")
		NumPut( 10,addr+0,"Char"),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,"Int64"),DllCall("RtlMoveMemory","PTR",addr+9,"PTR",buf?obj.GetAddress(k):&v,"PTR",sz),addr+=sz+9
		else NumPut(InStr(v,".")?9:v>4294967295?8:v>65535?6:v>255?4:v>-1?2:v>-129?1:v>-32769?3:v>-2147483649?5:7,addr+0,"Char")
			,NumPut(v,addr+1,InStr(v,".")?"Double":v>4294967295?"UInt64":v>65535?"UInt":v>255?"UShort":v>-1?"UChar":v>-129?"Char":v>-32769?"Short":v>-2147483649?"Int":"Int64")
			,addr+=InStr(v,".")||v>4294967295?9:v>65535?5:v>255?3:v>-129?2:v>-32769?3:v>-2147483649?5:9
	}
}

RawObjectSize(obj,buf:=0,objects:=0){
	if !objects
		objects:={(obj):1}
	else if !objects.HasKey(obj)
		objects[obj]:=1
	for k,v in obj
	{
		If IsObject(k)
			sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
		else 
			sz+=StrPut(k)*2+9
		If IsObject(v)
			sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
		else 
			sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
	}
	return sz
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

8

Re: AHK: Сравнение массива с массивом

Есть у кого мысли по поводу предыдущего поста, не нашёл в справке про то что бинарные данные можно сравнивать.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

9 (изменено: stealzy, 2017-11-14 23:20:09)

Re: AHK: Сравнение массива с массивом

serzh82saratov, как показали мои недавние опыты, небольшие бинарные данные сравнивать можно, но с некого предела простое сравнение дает ложноположительный результат.

st:=A_TickCount
File1 = D:\файл
File2 = D:\файл2
FileGetSize size1, % File1, K
FileGetSize size2, % File2, K
FileRead F1, *c %File1%
FileRead F2, *c %File2%
dur:=A_TickCount-st
MsgBox % (F1==F2) ", Speed - " Round((size1+size2)/dur/0x100000*1000, 3) " Gb/s"

Я остановился на нативном CRC-32, для данных из памяти скорость порядка 130 Мб/с. Видел тесты, где xxHash на порядок превосходил по скорости, но его еще завести надо, без включения бинарного кода не обойдется.

File := "C:\файл"
FileGetSize size, % File, K
st:=A_TickCount
x:=CRC32_File(File)
dur:=A_TickCount-st
MsgBox % Round(size/dur/0x100000*1000, 3) " Gb/s,`nhash =" x
; 50Mb/s, up to 130 after load in memory. xxHash suppose to be 11 times faster in memory.

CRC32_File(filename) {
	if !(f := FileOpen(filename, "r", "UTF-8"))
		throw Exception("Failed to open file: " filename, -1)
	f.Seek(0)
	while (dataread := f.RawRead(data, 262144))
		crc := DllCall("ntdll.dll\RtlComputeCrc32", "uint", crc, "ptr", &data, "uint", dataread, "uint")
	f.Close()
	return Format("{:#x}", crc)
}
Win7x64 up to 2018, AutoHotkey 1.1.30.00

10

Re: AHK: Сравнение массива с массивом

По предыдущему посту попробуй:

a := ["123","222"]
b := ["123","222", 333]

MsgBox % ObjToData(a) = ObjToData(b)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

11

Re: AHK: Сравнение массива с массивом

teadrinker
Ноль выдаёт, как и должно.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

12

Re: AHK: Сравнение массива с массивом

stealzy
В 3 посте вариант с MD5, CRC-32 лучше?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

13 (изменено: stealzy, 2017-11-14 23:43:16)

Re: AHK: Сравнение массива с массивом

Он быстрее, вы ведь не боитесь, что хакеры будут намеренно подделывать хеш массива, чтобы ваш код ошибся?
MD5, SHA это другой тип хешей, намеренно созданных, чтобы осложнить целенаправленный поиск коллизий. Для контроля целостности быстрее будут не имеющие этого свойства хеши.

Win7x64 up to 2018, AutoHotkey 1.1.30.00

14

Re: AHK: Сравнение массива с массивом

serzh82saratov пишет:

teadrinker
Ноль выдаёт, как и должно.

Почему должно? У меня, например, 1 выдаёт. Как вы со stealzy пытаетесь сравнивать бинарные данные как строки?

stealzy пишет:
FileRead F1, *c %File1%
FileRead F2, *c %File2%
dur:=A_TickCount-st
MsgBox % (F1==F2) 

Улыбнуло.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

15 (изменено: serzh82saratov, 2017-11-15 00:01:23)

Re: AHK: Сравнение массива с массивом

Да, работает в 4 раза быстрее.


a := ["123", "123", "123", "222"]
b := ["123", "123", "123", "222"]

MsgBox % ObjToCRC32(a) = ObjToCRC32(b)

ObjToCRC32(obj) {
	If !IsObject(obj)
		Return
	VarSetCapacity(Bin, Size := RawObjectSize(obj, 0) + 8, 0)
	RawObject(obj, NumPut(Size - 8, &Bin, "Int64"), 0)
	Return CalcCRC32Hash(&Bin, Size)
}

RawObject(obj, addr, buf := 0, objects := 0) {
	; Type.Enum:    Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
	; Negative for keys and positive for values
	if !objects
		objects:={(""):0,(obj):0}
	else objects[obj]:=(++objects[""])
	for k,v in obj
	{ ; 9 = Int64 for size and Char for type
		If IsObject(k){
			If objects.HasKey(k)
				NumPut(-12,addr+0,"Char"),NumPut(objects[k],addr+1,"Int64"),addr+=9
			else NumPut(-11,addr+0,"Char"),NumPut(sz:=RawObjectSize(k,buf),addr+1,"Int64"),RawObject(k,addr+9,buf,objects),addr+=sz+9
		}else if (k+0="")
			NumPut(-10,addr+0,"Char"),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,"Int64"),addr+=sz+9
		else NumPut( InStr(k,".")?-9:k>4294967295?-8:k>65535?-6:k>255?-4:k>-1?-2:k>-129?-1:k>-32769?-3:k>-2147483649?-5:-7,addr+0,"Char")
			,NumPut(k,addr+1,InStr(k,".")?"Double":k>4294967295?"UInt64":k>65535?"UInt":k>255?"UShort":k>-1?"UChar":k>-129?"Char":k>-32769?"Short":k>-2147483649?"Int":"Int64")
			,addr+=InStr(k,".")||k>4294967295?9:k>65535?5:k>255?3:k>-129?2:k>-32769?3:k>-2147483649?5:9
		If IsObject(v){
			if objects.HasKey(v)
				NumPut( 12,addr+0,"Char"),NumPut(objects[v],addr+1,"Int64"),addr+=9
			else NumPut( 11,addr+0,"Char"),NumPut(sz:=RawObjectSize(v,buf),addr+1,"Int64"),RawObject(v,addr+9,buf,objects),addr+=sz+9
			}else if (v+0="")
		NumPut( 10,addr+0,"Char"),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,"Int64"),DllCall("RtlMoveMemory","PTR",addr+9,"PTR",buf?obj.GetAddress(k):&v,"PTR",sz),addr+=sz+9
		else NumPut(InStr(v,".")?9:v>4294967295?8:v>65535?6:v>255?4:v>-1?2:v>-129?1:v>-32769?3:v>-2147483649?5:7,addr+0,"Char")
			,NumPut(v,addr+1,InStr(v,".")?"Double":v>4294967295?"UInt64":v>65535?"UInt":v>255?"UShort":v>-1?"UChar":v>-129?"Char":v>-32769?"Short":v>-2147483649?"Int":"Int64")
			,addr+=InStr(v,".")||v>4294967295?9:v>65535?5:v>255?3:v>-129?2:v>-32769?3:v>-2147483649?5:9
	}
}

RawObjectSize(obj,buf:=0,objects:=0){
	if !objects
		objects:={(obj):1}
	else if !objects.HasKey(obj)
		objects[obj]:=1
	for k,v in obj
	{
		If IsObject(k)
			sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
		else 
			sz+=StrPut(k)*2+9
		If IsObject(v)
			sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
		else 
			sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
	}
	return sz
}

CalcCRC32Hash(addr, length) {
	crc := DllCall("ntdll.dll\RtlComputeCrc32", "uint", crc, "ptr", addr, "uint", length, "uint")
	Return Format("{:#x}", crc)
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

16 (изменено: teadrinker, 2017-11-14 23:48:28)

Re: AHK: Сравнение массива с массивом

stealzy пишет:

Улыбнуло измерение скорости чтения с диска или строгое сравнение?

Ну, чтобы долго не объяснять, попробуйте:

FileRead, var, *с %A_AhkPath%
MsgBox, % var
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

17

Re: AHK: Сравнение массива с массивом

teadrinker пишет:

Почему должно? У меня, например, 1 выдаёт.

Массивы из 10 с кодом из 7 у меня ноль, 0. Странно что у нас по разному.

teadrinker пишет:

Ну, чтобы долго не объяснять, попробуйте:

Так остальные данные видимо просто не отображаются как символы.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

18

Re: AHK: Сравнение массива с массивом

serzh82saratov пишет:

Так остальные данные видимо просто не отображаются как символы.

Дело не в том, что они не отображаются. А в том, что AHK под строкой подразумевает то, что справа ограничивается одним или двумя нулевыми байтами. Т. е. при подобной проверке ты сравниваешь только части данных до первых двух нулевых байтов в случае Unicode-версии.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

19

Re: AHK: Сравнение массива с массивом

Понятно, значит так нельзя сравнивать.
По теме, пока считаем 16 пост решением.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

20

Re: AHK: Сравнение массива с массивом

stealzy пишет:

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

Winapi-функции вроде нет.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

21

Re: AHK: Сравнение массива с массивом

Нашел. Тема 12 летней давности от Lazlo:
https://autohotkey.com/board/topic/4388 … d-compare/

Win7x64 up to 2018, AutoHotkey 1.1.30.00

22

Re: AHK: Сравнение массива с массивом

serzh82saratov пишет:

Есть у кого мысли по поводу предыдущего поста, не нашёл в справке про то что бинарные данные можно сравнивать.

Мож это?

AutoHotkey(RUS).chm пишет:

Переменные и выражения
...
^ Побитовое исключающиее ИЛИ (^)

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

23

Re: AHK: Сравнение массива с массивом

teadrinker пишет:
stealzy пишет:

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

Winapi-функции вроде нет.

RtlCompareMemory?
https://msdn.microsoft.com/en-us/librar … s.85).aspx

24

Re: AHK: Сравнение массива с массивом

https://autohotkey.com/boards/viewtopic … dac5#p9976

MsgBox % FileCompare("D:\Image_004.png"
	, "D:\11.gif")
;Pass a relative or absolute filename for each file1 and file2
;Returns true if the contents of file1 = file2, or false if there are differences
FileCompare(file1, file2)
{
  FileGetSize, sFile1, %file1%
  FileGetSize, sFile2, %file2%
  if (sFile1 != sFile2)
    return 0  ;Not the same size so impossible to have the same contents
  FileRead, bFile1, *c %file1%
  FileRead, bFile2, *c %file2%
  return sFile1 = DllCall("ntdll\RtlCompareMemory", "ptr", &bFile1, "ptr", &bFile2, "ptr", sFile1)
}

Интересно, что Lazlo использовал в своем коде RtlFillMemory, RtlMoveMemory, а для сравнения задействовал memcmp из библиотеки msvcrt.

Win7x64 up to 2018, AutoHotkey 1.1.30.00

25

Re: AHK: Сравнение массива с массивом

Оба варианта вроде работают:

VarSetCapacity(var1, 4, 0)
VarSetCapacity(var2, 4, 0)

VarSetCapacity(var3, 4, 0)
VarSetCapacity(var4, 4, 0)

Loop 4  {
   i := A_Index
   Loop 4
      NumPut( (i = 4 && A_Index = 4) ? 2 : 1, var%i%, A_Index - 1, "UChar")  ; четвёртый буфер отличается
}

MsgBox, % DllCall("NtDll\RtlCompareMemory", Ptr, &var1, Ptr, &var2, Ptr, 4, Ptr)
MsgBox, % DllCall("NtDll\RtlCompareMemory", Ptr, &var3, Ptr, &var4, Ptr, 4, Ptr)

MsgBox, % DllCall("msvcrt\memcmp", Ptr, &var1, Ptr, &var2, Ptr, 4)
MsgBox, % DllCall("msvcrt\memcmp", Ptr, &var3, Ptr, &var4, Ptr, 4)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

26 (изменено: stealzy, 2017-11-15 04:53:32)

Re: AHK: Сравнение массива с массивом

А, понял, RtlCompareMemory может не быть в XP.

Win7x64 up to 2018, AutoHotkey 1.1.30.00

27

Re: AHK: Сравнение массива с массивом

Написано, что доступна, начиная с Windows 2000.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

28 (изменено: serzh82saratov, 2017-11-16 10:39:14)

Re: AHK: Сравнение массива с массивом

a := ["123", "123", "123", "222"]
b := ["123", "123", "123", "222"]

MsgBox % ArrayCompare(a, b)

ArrayCompare(obj1, obj2) {
	Loop 2
		VarSetCapacity(Bin%A_Index%, Size%A_Index% := RawObjectSize(obj%A_Index%, 0) + 8, 0)
		, RawObject(obj%A_Index%, NumPut(Size%A_Index% - 8, &Bin%A_Index%, "Int64"), 0)
	If (Size1 != Size2)
		Return 0
	Return !DllCall("msvcrt\memcmp", Ptr, &Bin1, Ptr, &Bin2, Ptr, Size1)
	  ;	Return Size1 = DllCall("NtDll\RtlCompareMemory", Ptr, &Bin1, Ptr, &Bin2, Ptr, Size1, Ptr)
}

RawObject(obj, addr, buf := 0, objects := 0) {
	; Type.Enum:    Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
	; Negative for keys and positive for values
	If !objects
		objects:={(""):0,(obj):0}
	Else
		objects[obj]:=(++objects[""])
	for k, v in obj
	{ ; 9 = Int64 for size and Char for type
		If IsObject(k) {
			If objects.HasKey(k)
				NumPut(-12,addr+0,"Char"),NumPut(objects[k],addr+1,"Int64"),addr+=9
			Else
				NumPut(-11,addr+0,"Char"),NumPut(sz:=RawObjectSize(k,buf),addr+1,"Int64"),RawObject(k,addr+9,buf,objects),addr+=sz+9
		} Else
			NumPut(-10,addr+0,"Char"),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,"Int64"),addr+=sz+9
		If IsObject(v) {
			If objects.HasKey(v)
				NumPut(12,addr+0,"Char"),NumPut(objects[v],addr+1,"Int64"),addr+=9
			Else
				NumPut(11,addr+0,"Char"),NumPut(sz:=RawObjectSize(v,buf),addr+1,"Int64"),RawObject(v,addr+9,buf,objects),addr+=sz+9
		} Else
			NumPut(10,addr+0,"Char"),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,"Int64"),DllCall("RtlMoveMemory","PTR",addr+9,"PTR",buf?obj.GetAddress(k):&v,"PTR",sz),addr+=sz+9
	}
}

RawObjectSize(obj,buf:=0,objects:=0){
	If !objects
		objects:={(obj):1}
	Else If !objects.HasKey(obj)
		objects[obj]:=1
	for k, v in obj
	{
		If IsObject(k)
			sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
		Else
			sz+=StrPut(k)*2+9
		If IsObject(v)
			sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
		Else
			sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
	}
	Return sz
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

29 (изменено: kolotilov256, 2020-03-05 18:53:15)

Re: AHK: Сравнение массива с массивом

Хэш суммы это конечно хорошо, но старый дедовский метод работает в 5 раз быстрее (Проверял через A_TickCount)

equal(Array1,Array2) {
   if !Array1[1] and !Array2[1] {
      if (Array1 = Array2)
         return true
      else return false
   } else {
      leng1 := Array1.Length()
      leng2 := Array2.Length()
      if (leng1 = leng2) {
         Loop % leng1 {
            if !equal(Array1[A_Index], Array2[A_Index])
               return false
         } return true
      } else return false
   }
}

Также держите ещё бонусом функцию find(Array, Var) для поиска элемента Var в массиве Array (Var тоже может быть массивом)

find(Array,Var) {
	For i, val in Array
		if equal(val,Var) or find(val,Var)
			return true
		
    return false
}

30

Re: AHK: Сравнение массива с массивом

kolotilov256
Ваша не работает:

a := [[]]
b := [[]]
MsgBox, % equal(a, b)

equal(Array1,Array2) {
   if !Array1[1] and !Array2[1] {
      if (Array1 = Array2)
         return true
      else return false
   } else {
      leng1 := Array1.Length()
      leng2 := Array2.Length()
      if (leng1 = leng2) {
         Loop % leng1 {
            if !equal(Array1[A_Index], Array2[A_Index])
               return false
         } return true
      } else return false
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

31

Re: AHK: Сравнение массива с массивом

teadrinker, да, не учёл частные случаи)
Теперь кажись нормально.

equal(Array1,Array2) 
{
   if !isObject(Array1) 
   {
      if (Array1 == Array2)
         return true
      else return false
   }
   else
   {
      leng1 := Array1.Length()
      leng2 := Array2.Length()
      if (leng1 = leng2) 
      {
         Loop % leng1 
            if !equal(Array1[A_Index], Array2[A_Index])
               return false
         return true
      }
      else return false
   }
}

32

Re: AHK: Сравнение массива с массивом

Тоже не совсем:

a := [1]
a[3] := 3
b := [1, "", 3]
MsgBox, % equal(a, b)
MsgBox, % a.HasKey(2) "`n" b.HasKey(2)

equal(Array1,Array2) 
{
   if !isObject(Array1) 
   {
      if (Array1 == Array2)
         return true
      else return false
   }
   else
   {
      leng1 := Array1.Length()
      leng2 := Array2.Length()
      if (leng1 = leng2) 
      {
         Loop % leng1 
            if !equal(Array1[A_Index], Array2[A_Index])
               return false
         return true
      }
      else return false
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

33 (изменено: kolotilov256, 2020-03-06 19:31:35)

Re: AHK: Сравнение массива с массивом

teadrinker
Ну такие тонкости в реальной работе с массивом никак не помешают.
Тем не менее

if (a[2] == b[2])
	msgbox true
else msgbox false

выдает true, значит в ходе какого-нибудь процесса моя функция не должна поломать алгоритм.

34

Re: AHK: Сравнение массива с массивом

Так это неправильно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

35

Re: AHK: Сравнение массива с массивом

В моём случае эквивалентными массивами являются массивы, элементы которых соответственно равны.

36

Re: AHK: Сравнение массива с массивом

Всё правильно, но только в моём примере элементы не равны. В первом массиве просто нет второго элемента, во втором он пустой, это не одно и то же.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg