Sign in to follow this  
Followers 0
MyEarth

Difference arrays of different size

24 posts in this topic

Hello, searching around has only confuse my ideas. I need to compare two 1D array, the have different size ( the first is smaller then the second ) and i need to get only the difference between the arrays. Fastest as possible, not case sensitive because they are unique value, is not very large min 200 max 700 or more but time is money so :shifty:

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

I can't post it, there are sensible information inside. The entry is composed by single word, without any space, can contains also numbers. I think is already sorted but i'm not sure about it. About the "difference" i mean

array1 = abc def ghi

array2 = abc cde def ghi

The result i want is "cde" because isn't present in the first array. The first array as i have said before is smaller or equal then the second one. I think is all. thanks for your help.

Edited by MyEarth

Share this post


Link to post
Share on other sites

What have you tried already: script? Because you are not in restaurant where you can order what you want. Make a example which fills the arrays whith test elements, and then i or somebody else try to find the fastest solution. 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

MyEarth,

Define "difference" between arrays.

kylomas

edit: For example, what is the difference between these two arrays

local $a1 = [1,1,1,4,5,6,7,8,9,0]
local $a2 = [3,4,5,6,7,8,9,0,'a','b',1,2]

 

Edited by kylomas
question

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Kylomas, i think the difference are 2,3,a,b so the entry missing from the first array but present in the second one. No duplicate will be present in the array so will never happen 1,1,1,1 but only 1 one, anyway i can use ArrayUnique before if i'll found some. I'll just want to know what entry from the second array are not present in the first one, the "difference" i don't know how to explain better. AutoBert a pizza for me, thanks...

EDIT: I think i have found the script i need:

 

I'll test it more.

 

Edited by MyEarth

Share this post


Link to post
Share on other sites

Easier and faster  :)

#include <Array.au3>

local $a = [1,1,1,4,5,6,7,8,9,0,'C']
local $b = [3,4,5,6,7,8,9,0,'a','b','c',1,2]

Local $sdb = ObjCreate("Scripting.Dictionary")
$sdb.CompareMode = 1   ; case insensitive
For $i In $b
    $sdb.Item($i)
Next
For $i In $a
    If $sdb.Exists($i) Then $sdb.Remove($i)
Next
$asdb = $sdb.Keys()
_ArrayDisplay($asdb, "$asdb")

 

Share this post


Link to post
Share on other sites

Cool, thanks. Just a question, your code with COM don't require any error checking except for see if the variable is an array?

Share this post


Link to post
Share on other sites

Using the same data as follows on mikell's example, post#8, I got 11 ms.
My tests took about 24 ms.

Although my examples are slower by about 13 ms, I still posted because of the possible options made available.

#include <Array.au3>

;Local $aArray1 = ["abc", "jkl", "def", "ghi"]
;Local $aArray2 = ["abc", "cde", "def", "ghi", "hij"]

;#cs
; ----- Create sample arrays ------------
Global $aArray1[500]
For $n = 0 To UBound($aArray1) - 1
    $aArray1[$n] = ($n * 2) + 1
Next
Global $aArray2[1000]
For $n = 0 To UBound($aArray2) - 1
    $aArray2[$n] = $n; Odd numbers only
Next
; -----> End of Create sample arrays ------------
;#ce

Global $iTimer = TimerInit()
ConsoleWrite("Elements in $array2 but not in $array1" & @LF)
ConsoleWrite(_ArrayDiff($aArray1, $aArray2) & @LF)
ConsoleWrite(TimerDiff($iTimer) & " ms ===========" & @LF) ; 24 ms

Global $iTimer = TimerInit()
ConsoleWrite("Elements in $array1 but not in $array2" & @LF) ; 24 ms
ConsoleWrite(_ArrayDiff($aArray1, $aArray2, 2) & @LF)
ConsoleWrite(TimerDiff($iTimer) & " ms ===========" & @LF)

Global $iTimer = TimerInit()
ConsoleWrite("Elements Not found in both arrays." & @LF)
ConsoleWrite(_ArrayDiff($aArray1, $aArray2, 3) & @LF)
ConsoleWrite(TimerDiff($iTimer) & " ms ===========" & @LF) ; 23 ms

Global $iTimer = TimerInit()
$arr = _ArrayDiff($aArray1, $aArray2, 3, 0)
_ArrayDisplay($arr, TimerDiff($iTimer) & " ms Elements Not found in both arrays.") ; 24 ms


; -------------------------------------------------
; Function:  _ArrayDiff
; Purpose:  Comparing elements in two arrays and returning the differences depending on the value of the parameter $iRet.
; Parameter:-
;           $array1 and $array2 are the arrays to be compared.
;           $iRet = 1 ; Returns elements in $array2 but not in $array1. (default)
;           $iRet = 2 ; Returns elements in $array1 but not in $array2.
;           $iRet = 3 ; Returns elements Not found in both arrays.
;           $String = 1 ; Returns elements as a string separated by @lf. (default)
;           $String = 0 ; Returns elements as an array.
; Author: Malkey
; -------------------------------------------------
Func _ArrayDiff(ByRef $array1, ByRef $array2, $iRet = 1, $String = 1)
    If (Not IsArray($array1)) Or (Not IsArray($array2)) Then Return SetError(1, 0, -1)
    Local $sArrayToString = _ArrayToString($array2, @LF) & @LF
    Local $sString2
    For $i = 0 To UBound($array1) - 1
        $sArrayToString = StringRegExpReplace($sArrayToString, "(?m)^" & $array1[$i] & "\R", "")
        If @extended = 0 Then $sString2 &= $array1[$i] & @LF ; Check items in $array1 but not in $array2
    Next
    Switch $iRet
        Case 1
            $sRet = StringStripWS($sArrayToString, 2)
        Case 2
            $sRet = StringStripWS($sString2, 2)
        Case 3
            $sRet = StringStripWS($sArrayToString & $sString2, 2)
    EndSwitch
    
    ;Return array or string
    If $String Then
        Return $sRet
    Else
        Return StringSplit($sRet, @LF, 2)
    EndIf
EndFunc   ;==>_ArrayDiff


 

Share this post


Link to post
Share on other sites

I'm sure I've known the answer to this before, but I've forgotten and it is thread relevant.

Why does this expression evaluate as true?

local $a = [1,1,1,4,5,6,7,8,9,0,'C']
local $b = [3,4,5,6,7,8,9,0,'a','b','c',1,2]

ConsoleWriteLine(($a == $b))

Func ConsoleWriteLine($msg)
    ConsoleWrite($msg & @CRLF)
EndFunc

 


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

Maybe because $a and $b are not strings ?  :)

==   : Tests if two strings are equal

Share this post


Link to post
Share on other sites

Sorry, it was a small part of the answer indeed

== : Tests if two strings are equal. Case sensitive. The left and right values are converted to strings if they are not strings already.

local $a = [1,1,1,4,5,6,7,8,9,0,'C']
Msgbox(0,"", String($a))

local $b = 2
Msgbox(0,"", String($b))
   

Share this post


Link to post
Share on other sites

I understand
I just had a look into the wiki here , but the sample code brings no clarification because it uses the operator "==" (which obviously can't work) and not "="

Share this post


Link to post
Share on other sites

#17 ·  Posted

@Malkey: I was using _ArrayDiff with arrays of directories that have "\" as the last character of each element ... and the Diff operation lets them through.

Any suggestion of how to make it work with \'s?

 

ArrayDiff Fail.png

Share this post


Link to post
Share on other sites

#18 ·  Posted

3 hours ago, qwert said:

Any suggestion of how to make it work with \'s?

Yes. Use a Scripting.Dictionary based code like mine in post#8

or...

apply the change below to Malkey's _ArrayDiff   :)

$sArrayToString = StringRegExpReplace($sArrayToString, "(?m)^\Q" & $array1[$i] & "\E\R", "")

 

Share this post


Link to post
Share on other sites

#19 ·  Posted

Quote

Use a Scripting.Dictionary based code like mine in post#8

Actually, I tried your method, first ... and came up with a "null" array.  Since I know nothing about Objects and their use, I switched to Malkey's function.

So, thanks for the suggestion for Malkey's script.  It works.  (I'm afraid I've never gotten the hang of reading RegExp's.)

Non-the-less, would you mind showing your method using the following arrays?  I'd like to understand how to use it.  From the discussion, it seems to be faster.

Quote

Local $aArray1 = ["abc", "jkl", "def\", "ghi", "Users\"]
Local $aArray2 = ["abc", "cde", "Users\", "def\", "ghi", "hij"]

 

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

Something like this should work  :)

#include <Array.au3>

local $a = ["abc", "jkl", "def\", "ghi", "Users\"]
local $b = ["abc", "cde", "Users\", "def\", "ghi", "hij"] 

; create 3 empty dictionaries
Local $sda = ObjCreate("Scripting.Dictionary")
Local $sdb = ObjCreate("Scripting.Dictionary")
Local $sdc = ObjCreate("Scripting.Dictionary")
; set comparemode property
$sda.CompareMode = 1   ; case insensitive
$sdb.CompareMode = 1  
; populate 'a' and 'b' dictionaries with the content of 'a' and 'b' arrays
; the elements are added as keys
For $i In $a
    $sda.Item($i)
Next
For $i In $b
    $sdb.Item($i)
Next
; check if elements in array 'a' exist as keys in dictionary 'b'
; if not then add them to dictionary 'c'
For $i In $a
    If not $sdb.Exists($i) Then $sdc.Item($i)
Next
; check if elements in array 'b' exist as keys in dictionary 'a'
; if not then add them to dictionary 'c'
For $i In $b
    If not $sda.Exists($i) Then $sdc.Item($i)
Next
; return the array of all keys from dictionary 'c'
$asdc = $sdc.Keys()
_ArrayDisplay($asdc, "$asdc")

Edit
another example in this topic - post#10

Edited by mikell
1 person likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0