Jump to content

text file comparison


Senach
 Share

Recommended Posts

Greetings all.

I'm having a bit of trouble and have exhausted my troubleshooting abilities. I've done some searching in the forums and while I found several post similar to what I'm trying I was unable to adapt the given code to make it work for me.

Basically, I have two text files. One is a list of book titles, the other is a list of some of the titles on the first list. All the titles on the second list are in the fist, and the formatting is identical on both lists. I'm trying to basically combine the two lists and make note (in the case of my script below putting a * in front of them) of the titles that are on the second list.

Here's what I have (I have it outputting to a third file because I just going for the simplest way I knew):

#include <File.au3>

    $filea = FileOpen("C:\script\alltitles.txt", 0)
    $file8 = FileOpen("C:\scripts\goodtitles.txt", 0)   
    $fileZeta = FileOpen("C:\scripts\totaltitles.txt", 10)

While 1
$line = filereadline($file8)
    if @error = -1 then ExitLoop
        if @error <> -1 then readwrite()

WEnd

FileClose($filea)
FileClose($file8)
FileClose($fileZeta)

Func readwrite()
    While 1
        $line2 = FileReadLine($filea)
        If @error = -1 then ExitLoop
            If $line = $line2 Then FileWriteLine ($fileZeta, "*" & $line2 & @CRLF)
            If $line <> $line2 Then FileWriteLine ($fileZeta, $line2 & @CRLF)
    WEnd
EndFunc

Any thoughts or suggestions to where I'm messing up would be greatly appreciated.

Thanks!

"The three rules of the Librarians of Time and Space are: 1) Silence; 2) Books must be returned no later than the date last shown; and 3) Do not interfere with the nature of causality." Terry Pratchett - The Light Fantastic

Link to comment
Share on other sites

Thanks Bugfix - that is a very sweet function, but either Im missing something or I wasnt making myself clear. Let me explain my quandary in a bit more detail:

I run a homebound patron service at my library where we take books to people who cant come in. when we pick up these books the patrons have rated them on a scale a 1-10. We enter those numbers into our library computer system. However the library system will only give us lists of the patrons books that they rated X number or above. Well, we can get a list of books they like (say that they rated 8 and above), and a list of all the books weve taken them (they dont like it when we take the same book twice). But not a list of all the books we've taken the patron with what they'd rated them. So naturally all the books on the 8+ list are on the list of all of them. So when were picking new books we either have to have both lists and check both as we pick new books, or take to list of all the books and go through and highlight ones on that list that are on the 8+ list. While this works, when the list of all items is over 600 books, and the list of 8+ has over 200, it takes a while. I was trying to figure out a way to automate the highlighting chore basically mark all the ones on the 8+ list on the all books list.

Anyway, does that make sense? Your _GetIntersection function seems to be designed to either pull out the differences or similarities between two arrays. Well, I know everything on the 8+ list is on the all book list, but not vice versa.

So is there a way that Im just missing with that function to get all the ones on one list marked on the other? Or did I just not explain my original question well enough?

Thanks!

"The three rules of the Librarians of Time and Space are: 1) Silence; 2) Books must be returned no later than the date last shown; and 3) Do not interfere with the nature of causality." Terry Pratchett - The Light Fantastic

Link to comment
Share on other sites

@BugFix - congrats, very nice.

@Senach - something like this, using GetIntersection by BugFix

#include <array.au3>
#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <ListViewConstants.au3>
#include <Misc.au3>
#include <WindowsConstants.au3>

$sAll = 'book one,book two,title three,book four,title five,book six,title 7,book eight,tile nine'
$sPlus8 = 'title 7,book one,book 1,book 5,title 8,title three,book two'
$aFirstSet = StringSplit($sAll, ",")
$aPlus8 = StringSplit($sPlus8, ",")

$aRet = _GetIntersection($sAll, $aPlus8, 1, ',')
;_ArrayDisplay($aRet)

$Form1 = GUICreate("Intersect Items Ticked", 300, 270)
$hListView = GUICtrlCreateListView("Items", 10, 10, 280, 250, _
        BitOR($LVS_REPORT, $WS_HSCROLL, $WS_VSCROLL, $WS_BORDER), _
        BitOR($WS_EX_CLIENTEDGE, $LVS_EX_CHECKBOXES, $LVS_EX_FULLROWSELECT))
$j = 0
For $i = 1 To $aFirstSet[0]
    GUICtrlCreateListViewItem($aFirstSet[$i], $hListView)
    If $aFirstSet[$i] = $aRet[$j][0] Then
        GUICtrlSetState(-1, $GUI_CHECKED)
        $j += 1
    EndIf
Next
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 270)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_CLICK, $NM_DBLCLK, $NM_RCLICK, $NM_RDBLCLK
                    Return 1
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

;==================================================================================================
; Function Name:   _GetIntersection($Set1, $Set2 [, $GetAll=0 [, $Delim=Default]])
; Description::    Detect from 2 sets
;                  - Intersection (elements are contains in both sets)
;                  - Difference 1 (elements are contains only in $Set1)
;                  - Difference 2 (elements are contains only in $Set2)
; Parameter(s):    $Set1    set 1 (1D-array or delimited string)
;                  $Set2  set 2 (1D-array or delimited string)
;      optional:   $GetAll  0 - only one occurence of every different element are shown (Default)
;                           1 - all elements of differences are shown
;      optional:   $Delim   Delimiter for strings (Default use the separator character set by Opt("GUIDataSeparatorChar") )
; Return Value(s): Succes   2D-array    [i][0]=Intersection
;                                       [i][1]=Difference 1
;                                       [i][2]=Difference 2
;                  Failure  -1    @error  set, that was given as array, is'nt 1D-array
; Note:            Comparison is case-sensitiv! - i.e. Number 9 is different to string '9'!
; Author(s):       BugFix (bugfix@autoit.de)
;==================================================================================================
Func _GetIntersection(ByRef $Set1, ByRef $Set2, $GetAll = 0, $Delim = Default)
    Local $o1 = ObjCreate("System.Collections.ArrayList")
    Local $o2 = ObjCreate("System.Collections.ArrayList")
    Local $oUnion = ObjCreate("System.Collections.ArrayList")
    Local $oDiff1 = ObjCreate("System.Collections.ArrayList")
    Local $oDiff2 = ObjCreate("System.Collections.ArrayList")
    Local $tmp, $i
    If $GetAll <> 1 Then $GetAll = 0
    If $Delim = Default Then $Delim = Opt("GUIDataSeparatorChar")
    If Not IsArray($Set1) Then
        If Not StringInStr($Set1, $Delim) Then
            $o1.Add($Set1)
        Else
            $tmp = StringSplit($Set1, $Delim, 1)
            For $i = 1 To UBound($tmp) - 1
                $o1.Add($tmp[$i])
            Next
        EndIf
    Else
        If UBound($Set1, 0) > 1 Then Return SetError(1, 0, -1)
        For $i = 0 To UBound($Set1) - 1
            $o1.Add($Set1[$i])
        Next
    EndIf
    If Not IsArray($Set2) Then
        If Not StringInStr($Set2, $Delim) Then
            $o2.Add($Set2)
        Else
            $tmp = StringSplit($Set2, $Delim, 1)
            For $i = 1 To UBound($tmp) - 1
                $o2.Add($tmp[$i])
            Next
        EndIf
    Else
        If UBound($Set2, 0) > 1 Then Return SetError(1, 0, -1)
        For $i = 0 To UBound($Set2) - 1
            $o2.Add($Set2[$i])
        Next
    EndIf
    For $tmp In $o1
        If $o2.Contains($tmp) And Not $oUnion.Contains($tmp) Then $oUnion.Add($tmp)
    Next
    For $tmp In $o2
        If $o1.Contains($tmp) And Not $oUnion.Contains($tmp) Then $oUnion.Add($tmp)
    Next
    For $tmp In $o1
        If $GetAll Then
            If Not $oUnion.Contains($tmp) Then $oDiff1.Add($tmp)
        Else
            If Not $oUnion.Contains($tmp) And Not $oDiff1.Contains($tmp) Then $oDiff1.Add($tmp)
        EndIf
    Next
    For $tmp In $o2
        If $GetAll Then
            If Not $oUnion.Contains($tmp) Then $oDiff2.Add($tmp)
        Else
            If Not $oUnion.Contains($tmp) And Not $oDiff2.Contains($tmp) Then $oDiff2.Add($tmp)
        EndIf
    Next
    Local $UBound[3] = [$oDiff1.Count, $oDiff2.Count, $oUnion.Count], $max = 1
    For $i = 0 To UBound($UBound) - 1
        If $UBound[$i] > $max Then $max = $UBound[$i]
    Next
    Local $aOut[$max][3]
    If $oUnion.Count > 0 Then
        $i = 0
        For $tmp In $oUnion
            $aOut[$i][0] = $tmp
            $i += 1
        Next
    EndIf
    If $oDiff1.Count > 0 Then
        $i = 0
        For $tmp In $oDiff1
            $aOut[$i][1] = $tmp
            $i += 1
        Next
    EndIf
    If $oDiff2.Count > 0 Then
        $i = 0
        For $tmp In $oDiff2
            $aOut[$i][2] = $tmp
            $i += 1
        Next
    EndIf
    Return $aOut
EndFunc   ;==>_GetIntersection
Link to comment
Share on other sites

Thank you both for your help and patience with me. I must be denser than usual, but even with you all laying it out for me I cant get it to work.

Picaxe, Ive tried

$filea = FileOpen("C:\scripts\homebound\homebound_textfiles\homebound_a1.txt", 0)
    $file8 = FileOpen("C:\scripts\homebound\homebound_textfiles\homebound_81.txt", 0)   

$sAll = $filea
$sPlus8 = $file8

And got the box with the check box and line 1 but I was unable to get it to give me anything. (i.e. it wouldnt let me right click or anything to retrieve the data)

Then I tried just pasting the text files in for the $sAll and $sPlus8. But I guess they were too large because AutoIt errored out with a Unterminated string. (I double checked but I had removed all and from the file before I pasted it in so the only ones were before and after the text.)

Anyway, Thanks again for your help, but this is apparently beyond my ken. I think Im going to put it on the shelf for now and maybe come back to it later. Maybe then I can get my head wrapped around it.

"The three rules of the Librarians of Time and Space are: 1) Silence; 2) Books must be returned no later than the date last shown; and 3) Do not interfere with the nature of causality." Terry Pratchett - The Light Fantastic

Link to comment
Share on other sites

Try this, error checking/handling for missing files etc needs to be added. I'm assuming the file format is one book title per line.

#include <array.au3>
#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <ListViewConstants.au3>
#include <Misc.au3>
#include <WindowsConstants.au3>
#Include <String.au3>

$sPlus8 = FileRead("C:\scripts\homebound\homebound_textfiles\homebound_81.txt")    
$aFirstSet = _StringSplit(FileRead("C:\scripts\homebound\homebound_textfiles\homebound_a1.txt"), @CRLF, 1)
$aRet = _GetIntersection($aFirstSet, $sPlus8, 1, @CRLF)

$Form1 = GUICreate("Intersect Items Ticked", 300, 270)
$hListView = GUICtrlCreateListView("Items", 10, 10, 280, 250, _
        BitOR($LVS_REPORT, $WS_HSCROLL, $WS_VSCROLL, $WS_BORDER), _
        BitOR($WS_EX_CLIENTEDGE, $LVS_EX_CHECKBOXES, $LVS_EX_FULLROWSELECT))
$j = 0
$iUbound = UBound($aFirstSet) -1
For $i = 0 To $iUbound
    GUICtrlCreateListViewItem($aFirstSet[$i], $hListView)
    If $aFirstSet[$i] = $aRet[$j][0] Then
        GUICtrlSetState(-1, $GUI_CHECKED)
        $j += 1
    EndIf
Next
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 270)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_CLICK, $NM_DBLCLK, $NM_RCLICK, $NM_RDBLCLK ; to prevent select hilite , $LVN_ITEMCHANGING
                    Return 1
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

;==================================================================================================
; Function Name:   _GetIntersection($Set1, $Set2 [, $GetAll=0 [, $Delim=Default]])
; Description::    Detect from 2 sets
;                  - Intersection (elements are contains in both sets)
;                  - Difference 1 (elements are contains only in $Set1)
;                  - Difference 2 (elements are contains only in $Set2)
; Parameter(s):    $Set1    set 1 (1D-array or delimited string)
;                  $Set2  set 2 (1D-array or delimited string)
;      optional:   $GetAll  0 - only one occurence of every different element are shown (Default)
;                           1 - all elements of differences are shown
;      optional:   $Delim   Delimiter for strings (Default use the separator character set by Opt("GUIDataSeparatorChar") )
; Return Value(s): Succes   2D-array    [i][0]=Intersection
;                                       [i][1]=Difference 1
;                                       [i][2]=Difference 2
;                  Failure  -1    @error  set, that was given as array, is'nt 1D-array
; Note:            Comparison is case-sensitiv! - i.e. Number 9 is different to string '9'!
; Author(s):       BugFix (bugfix@autoit.de)
;==================================================================================================
Func _GetIntersection(ByRef $Set1, ByRef $Set2, $GetAll = 0, $Delim = Default)
    Local $o1 = ObjCreate("System.Collections.ArrayList")
    Local $o2 = ObjCreate("System.Collections.ArrayList")
    Local $oUnion = ObjCreate("System.Collections.ArrayList")
    Local $oDiff1 = ObjCreate("System.Collections.ArrayList")
    Local $oDiff2 = ObjCreate("System.Collections.ArrayList")
    Local $tmp, $i
    If $GetAll <> 1 Then $GetAll = 0
    If $Delim = Default Then $Delim = Opt("GUIDataSeparatorChar")
    If Not IsArray($Set1) Then
        If Not StringInStr($Set1, $Delim) Then
            $o1.Add($Set1)
        Else
            $tmp = StringSplit($Set1, $Delim, 1)
            For $i = 1 To UBound($tmp) - 1
                $o1.Add($tmp[$i])
            Next
        EndIf
    Else
        If UBound($Set1, 0) > 1 Then Return SetError(1, 0, -1)
        For $i = 0 To UBound($Set1) - 1
            $o1.Add($Set1[$i])
        Next
    EndIf
    If Not IsArray($Set2) Then
        If Not StringInStr($Set2, $Delim) Then
            $o2.Add($Set2)
        Else
            $tmp = StringSplit($Set2, $Delim, 1)
            For $i = 1 To UBound($tmp) - 1
                $o2.Add($tmp[$i])
            Next
        EndIf
    Else
        If UBound($Set2, 0) > 1 Then Return SetError(1, 0, -1)
        For $i = 0 To UBound($Set2) - 1
            $o2.Add($Set2[$i])
        Next
    EndIf
    For $tmp In $o1
        If $o2.Contains($tmp) And Not $oUnion.Contains($tmp) Then $oUnion.Add($tmp)
    Next
    For $tmp In $o2
        If $o1.Contains($tmp) And Not $oUnion.Contains($tmp) Then $oUnion.Add($tmp)
    Next
    For $tmp In $o1
        If $GetAll Then
            If Not $oUnion.Contains($tmp) Then $oDiff1.Add($tmp)
        Else
            If Not $oUnion.Contains($tmp) And Not $oDiff1.Contains($tmp) Then $oDiff1.Add($tmp)
        EndIf
    Next
    For $tmp In $o2
        If $GetAll Then
            If Not $oUnion.Contains($tmp) Then $oDiff2.Add($tmp)
        Else
            If Not $oUnion.Contains($tmp) And Not $oDiff2.Contains($tmp) Then $oDiff2.Add($tmp)
        EndIf
    Next
    Local $UBound[3] = [$oDiff1.Count, $oDiff2.Count, $oUnion.Count], $max = 1
    For $i = 0 To UBound($UBound) - 1
        If $UBound[$i] > $max Then $max = $UBound[$i]
    Next
    Local $aOut[$max][3]
    If $oUnion.Count > 0 Then
        $i = 0
        For $tmp In $oUnion
            $aOut[$i][0] = $tmp
            $i += 1
        Next
    EndIf
    If $oDiff1.Count > 0 Then
        $i = 0
        For $tmp In $oDiff1
            $aOut[$i][1] = $tmp
            $i += 1
        Next
    EndIf
    If $oDiff2.Count > 0 Then
        $i = 0
        For $tmp In $oDiff2
            $aOut[$i][2] = $tmp
            $i += 1
        Next
    EndIf
    Return $aOut
EndFunc   ;==>_GetIntersection

Edit: Use _StringSplit for zero based array so difference sets do not contain array count, in case they are used later.

Edited by picaxe
Link to comment
Share on other sites

Picaxe, That works beautifully! You Sir/Madam are a saint!

And almost as important as it working, I think I understand why its working now.

Thank you again, very, very much.

*bow*

"The three rules of the Librarians of Time and Space are: 1) Silence; 2) Books must be returned no later than the date last shown; and 3) Do not interfere with the nature of causality." Terry Pratchett - The Light Fantastic

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...