Results 1 to 27 of 27

Thread: [RESOLVED] Can someone help me with a List comparison?

  1. #1

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Resolved [RESOLVED] Can someone help me with a List comparison?

    I have a class called "ImageThumbnail", one field of which is an IO.FileInfo object. I have one ListA =List(Of ImageThumbnail) and another List B =List(Of IO.FileInfo).
    I want to find all the ImageThumbnails in ListA whose FileInfo isn't in ListB.

    I can't work out the right syntax to do this, despite all the examples in MSDN. I don't think I can take advantage of List.Contains because the FileInfo in ListA won't be the same object as the one I'm interested in in ListB; it will just have certain field values the same. So I have written a Comparer for FileInfos which overrides the Equals method, and that means I can use FileInfo.Equals. But I can't figure out how to fit it all together.

    Any suggestions gratefully received. Cheers, BB
    Last edited by boops boops; Mar 19th, 2010 at 12:32 PM.

  2. #2
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Can someone help me with a List comparison?

    Can you use LINQ?

    If so, perhaps something like this
    vb.net Code:
    1. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    2.         Dim ListA As New List(Of ImageThumbnail)
    3.         Dim ListB As New List(Of FileInfo)
    4.  
    5.         Dim result = From it As ImageThumbnail In ListA _
    6.                      Where Not ContainsFileInfo(ListB, it.FileInfo) _
    7.                      Select it
    8.     End Sub
    9.  
    10.     Private Function ContainsFileInfo(ByVal list As List(Of FileInfo), ByVal fi As FileInfo) As Boolean
    11.         For Each f As FileInfo In list
    12.             If f.Equals(fi) Then Return True
    13.         Next
    14.         Return False
    15.     End Function

    The ContainsFileInfo method is basically a replacement of the usual Contains method, only this time you can implement your own 'equality check' if the usual (reference-equality) is not right.

  3. #3
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    which version of vb.net are you using?
    can you post the ImageThumbnail class?

  4. #4
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by NickThissen View Post
    Can you use LINQ?
    i was going to suggest linq too

  5. #5
    Wait... what? weirddemon's Avatar
    Join Date
    Jan 2009
    Location
    USA
    Posts
    3,826

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by .paul. View Post
    i was going to suggest linq too
    Everyone <3 LINQ
    CodeBank contributions: Process Manager, Temp File Cleaner

    Quote Originally Posted by SJWhiteley
    "game trainer" is the same as calling the act of robbing a bank "wealth redistribution"....

  6. #6

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Thanks for your replies. I know next to nothing about Linq (I don't even get weird's joke) but I'll take it on trust that Nick's method will do the triq.

    I was half expecting something out of the quarter of the generic List and its dozens of new extension methods: System.Actions, System.Predicates, IComparables and other stuff I don't understand. I could swear I've seen syntax with a double-barrelled Of T, e.g.:
    Code:
    Delegate Teabreak As Long (of T) (of More T), Two Lumps Please
    (ok, I just made that up, but I hope someone knows what I mean). So far I have tried a few things with lambda functions which are nicely concise. But I found nothing that helped with the problem I raised in this thread. MSDN offers a dozen or so examples under List(Of T).FindAll Method, including this:
    FindAll(Predicate(Of T)):
    Find all books that whose Genre property is "Computer" using the FindComputer predicate delegate.
    That looks like it might answer my question. Frustratingly, it is the only one which has a dead link.

    So I'll leave this thread unresolved for the moment, to see if anyone can come up with alternatives in that direction.

    cheers, BB

  7. #7
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    BB post the ImageThumbnail class i'll have a go at a more precise linq assuming you're using vb2008+

  8. #8

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by .paul. View Post
    BB post the ImageThumbnail class i'll have a go at a more precise linq assuming you're using vb2008+
    That's kind of you, Paul. Basically the ImageThumbnail object is just a package of a small image with a fileInfo. At the moment it also contains several hundred lines of half-baked methods which probably belong somewhere else; but I trust you'll know what to ignore, so here it is as a zip.

    cheers, BB
    Attached Files Attached Files

  9. #9

  10. #10
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    try this:

    vb Code:
    1. Dim list1 As New List(Of IB_ThumbNail)
    2. Dim list2 As New List(Of IO.FileInfo)
    3.  
    4. Dim Thumbnails = (From item In list1 _
    5.                  Where Array.Find(list2.ToArray, Function(i) i Is item.Info) Is Nothing _
    6.                  Select item).ToArray
    7.  
    8. Dim list3 As New List(Of IB_ThumbNail)(Thumbnails)

  11. #11

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Hi Nick and Paul, I'm going to need a little time to try your examples out. It looks at first sight that they have a lot in common and I trust both are going to work. I'll do a timing comparison to see if there is any efficiency difference. Anyway, it's clear that I need to study the Linq syntax a bit so that I can apply the technique to different situations.

    I'm still interested to hear if there are alternative ways to solve the problem. Let's see what turns up.

    cheers, BB

  12. #12
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    My example is linq using a lambda function to search the array. Nick's example is nearly identical except it uses a seperate function with a loop, instead of an inline function to search the array.

  13. #13
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: Can someone help me with a List comparison?

    Since this is an object that you have created I would recommend adding the relevant functionality to the object. There is nothing wrong with using other methods but I would keep the object functions in the object for OOP perspective.
    If you want another approach than you can add ICamparable to the TambNale class and implement its CampareTo method. Here is an example:

    vb Code:
    1. Public Class IB_ThumbNail
    2.     Inherits UserControl
    3.     Implements IDisposable
    4.     Implements IComparable(Of IO.FileInfo)
    5.  
    6.     'Some functions here
    7.  
    8.     Public Function CompareTo(ByVal other As System.IO.FileInfo) As Integer Implements System.IComparable(Of System.IO.FileInfo).CompareTo
    9.         Return Me._info.FullName.CompareTo(other.FullName)
    10.     End Function
    11.  
    12. End Class
    I am comparing the full name of the FileInfo object but you can campare other value(s) at the same time.

  14. #14
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by VBDT View Post
    I am comparing the full name of the FileInfo object but you can campare other value(s) at the same time.
    you can also compare the complete fileinfo object, but i don't see how your example is usable in this scenario.

  15. #15

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by VBDT View Post
    Since this is an object that you have created I would recommend adding the relevant functionality to the object. There is nothing wrong with using other methods but I would keep the object functions in the object for OOP perspective.
    Thanks for your advice, which is certainly not wasted on me. I can sum up my present problem like this: how can I compare two generic lists, when one is Of Type A, and the other is of objects that have a field or property of Type A?

    bye, BB

  16. #16
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by .paul. View Post
    you can also compare the complete fileinfo object, but i don't see how your example is usable in this scenario.
    Well two objects are equal if they point to the same object. I don't think this is what he wants to do since a FileInfo object let say A that contains file info of "text.txt" and FileInfo object B that contains file info of "text.txt" are different objects but after all they contain the info of the same file. Should this be considered equal? I think yes.

    But I do agree with you that my example isn't helping to solve his problem after reading one more time his requirements.

  17. #17
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by boops boops View Post
    Thanks for your advice, which is certainly not wasted on me. I can sum up my present problem like this: how can I compare two generic lists, when one is Of Type A, and the other is of objects that have a field or property of Type A?

    bye, BB
    The example I posted will not help you for this, instead i came up with another one that will make the use of "Contains" method of the list. But this way of doing it requires that list type and the parameter type of "Contains" method be the same. In this example I implemented "IEqualityComparer" interface. Here is the example:

    vb Code:
    1. Public Class IB_ThumbNail
    2.     Implements System.Collections.Generic.IEqualityComparer(Of IB_ThumbNail)
    3.  
    4.     Dim _info As IO.FileInfo
    5.  
    6.     Public ReadOnly Property Info() As IO.FileInfo
    7.         Get
    8.             Return Me._info
    9.         End Get
    10.     End Property
    11.  
    12.     Sub New()
    13.     End Sub
    14.  
    15.     Sub New(ByVal fileName As String)
    16.         Me._info = New IO.FileInfo(fileName)
    17.     End Sub
    18.  
    19.     Public Function Equals1(ByVal x As IB_ThumbNail, ByVal y As IB_ThumbNail) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of IB_ThumbNail).Equals
    20.         Return x._info.FullName = y._info.FullName
    21.     End Function
    22.  
    23.     Public Function GetHashCode1(ByVal obj As IB_ThumbNail) As Integer Implements System.Collections.Generic.IEqualityComparer(Of IB_ThumbNail).GetHashCode
    24.         Return obj._info.GetHashCode
    25.     End Function
    26.  
    27. End Class

    And this is how you use it:
    vb Code:
    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2.         Dim tn As New IB_ThumbNail("test.txt")
    3.         Dim b As Boolean = thumbNailList.Contains(tn, CType(New IB_ThumbNail, Global.System.Collections.Generic.IEqualityComparer(Of IB_ThumbNail)))
    4.     End Sub
    Again, this might not be what you want since you what to compare two lists with different types.

  18. #18

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Thanks again VBDT. Probably it's clear I'm trying to make an image browser. At present each IB_Thumbnail contains a FileInfo and a thumbnail image. When I visit a folder the program generates the thumbnails for all the images it finds there. But that can take time, so I want to cache the IB_Thumbnails and just check the folder for changes. That's why I want to compare FileInfos in the cached thumbnails with those in the folder.

    I can't use generic List.Contains because the cached FileInfos will never be the same objects as the FileInfos read from disk -- even when they refer to the same images. Nick's custom Contains function (post #2) presents a feasible alternative. Clearly it depends on having an implementation of FileInfo.Equals: an IEqualityComparer such as the one you posted. That and Paul's solution, both of which use Linq, will probably work very well.

    The reason I am hanging out for something else is that I am trying to learn more about the possibilities of generics, and I don't want to take Linq on board for the moment. Surely something must be lurking among all the native methods and extensions of the Generic List? Taking a fresh trawl through msdn today, for example, I noticed that List(Of T).ConvertAll(Of TOutput) could be a way to turn the list of thumbnails into a list of FileInfos. That may turn out to be the way to go.

    Instead I could try to work something out using nested For loops. But I get the impression that Microsoft's newer methods will be more efficient as well as neater.

    BB

  19. #19
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Can someone help me with a List comparison?

    If you really don't want to use LINQ you can always just loop through all list elements yourself. But really, why? If you can compile to .NET 3.5, then LINQ is so much easier to write and read.
    Everyone with the smallest of programming backgrounds will know exactly what is going on if he sees this
    Code:
    From it As ImageThumbnail In ListA _
    Where Not ListB.Contains(it.FileInfo) _
    Select it
    It's translated to english very easily:
    Code:
    Select those ImageThumbnails in ListA where ListB does not contain their FileInfo properties
    The only 'glitch' is that you cannot use the ListB.Contains method because it does not check the filenames of the FileInfo but merely does a reference check. So you need a separate function (could also probably be done using inline functions or lambda expressions, but I don't know much about that) which makes it look a little less fancy.
    Really, you could create your own collection instead of ListB, and implement the contains method in that class the way you want it, and then you can just use ListB.Contains.

    My example should work just fine for you, provided that you implemented some kind of Equals function (which you said you did?). If not, you can simply replace the equals check by a check 'If f.FullName = fi.FullName'. Then it would match those FileInfo objects that point to the same file (but are not necessarily the same object).

    Perhaps you are thrown off by the fact that I use a 'primitive' loop in the Contains method. But really, all other Contains methods do the exact same loop behind the scenes. Just get .NET Reflector and take a look for yourself. Also, LINQ most probably does very similar loops behind the scenes. It's not some magic new feature that does things completely differently, it is merely 'syntactic sugar' (as I've seen it called) and in the end it all translates to loops.

  20. #20

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by NickThissen View Post
    If you really don't want to use LINQ you can always just loop through all list elements yourself. But really, why? If you can compile to .NET 3.5, then LINQ is so much easier to write and read.
    I have absolutely nothing against LINQ. It's just that I had decided to spend some more time learning about the generics. If LINQ is capable of replacing all the FindAlls, System.Predicates etc. then I agree that it would better to spend my time on that instead. Certainly it's easier to read and I suppose it is more widely applicable.

    Meanwhile, after spending far too long struggling with the List alternatives I have come up with something so simple that I am kicking myself for not having thought of it before. Probably you are mentally kicking me too.

    I added this little function to the IB_Thumbnail class:
    vb.net Code:
    1. Public Function InfoEquals(ByVal Info As IO.FileInfo) As Boolean
    2.    With Me.Info
    3.        Return .FullName = Info.FullName AndAlso _
    4.               .LastWriteTime = Info.LastWriteTime AndAlso _
    5.               .Length = Info.Length
    6.    End With
    7. End Function
    And that makes it easy to do things like this:
    vb.net Code:
    1. For Each info As FileInfo In InfoList
    2.    Dim f As FileInfo = info
    3.    ThumbnailList.Remove(ThumbnailList.Find _
    4.                         (Function(thumb As IB_ThumbNail) _              
    5.                         thumb.InfoEquals(f)))
    6. Next
    I already had an implementation of ICompareEquals for FileInfos, but it seems for the while I can make do without it. (In fact I wonder why people bother with that kind of complication; but that will probably become clear to me sooner or later.)

    Everyone with the smallest of programming backgrounds will know exactly what is going on if he sees this
    Er, are you referring to me?
    Code:
    Public Class Boops_Boops
    Implements IGnorant
    '...
    End Class
    thanks again one and all,
    BB

  21. #21
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    wouldn't this work?

    vb Code:
    1. Public Function InfoEquals(ByVal Info As IO.FileInfo) As Boolean
    2.     Return Me.info.Equals(Info)
    3. End Function

  22. #22

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Not without an implementation of ICompareEquals which shadows the default Equals function and compares only the relevant fields. FileInfo is a reference type, so the default Equals would do a bitwise comparison of the whole object.

    By way of illustration, FileInfo has a LastAccessed property which changes every time the file is opened. But I don't want to check that when deciding if the image has changed. If I used the default Equals, I would have to regenerate the thumbnail every time the image was viewed.

    Besides, ICompareEquals can only compare two objects of the same type. The nice thing about my IB_Thumbnail.InfoEquals function is that it compares a Thumbnail to a FileInfo; and that's what makes the inline function possible.

    BB

  23. #23
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,424

    Re: Can someone help me with a List comparison?

    point taken then (after i tested it anyway). my linq wouldn't have worked after all.

    just a pointer, .findall is used the same way as .find with the difference being it returns an array instead of a single element

  24. #24
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Can someone help me with a List comparison?

    Just a little note here; I am pretty sure that most solutions to your problem mentioned here would result in very similar (if not exactly the same) code (eventually). Whether you use LINQs query syntax or its function syntax, or even the Find method you ended up using: they all use some kind of loop behind the scenes. There is simply no other way to implement a linear search then to check every item (at least until a match is found). Sure, you can do better than linear searches if your data is structured in some special way (dictionaries, heaps, trees, etc), but in a List(Of T) that is not the case. To find an item that matches some specification, you will need to try every item until one is found.

    So, I guess in the end you need to use whichever feels more comfortable for you. For me, that is LINQ because it is so easy to read. You might prefer its function syntax, in which case you should use that

    In case you're wondering, this is the difference
    vb.net Code:
    1. Dim lst As New List(Of Button)
    2.         Dim lst2 As New List(Of TreeView)
    3.  
    4.         'query syntax
    5.         Dim matches = From b As Button In lst _
    6.                       Where b.Tag IsNot Nothing _
    7.                       AndAlso TypeOf b.Tag Is TreeView _
    8.                       AndAlso DirectCast(b.Tag, TreeView).Nodes.Count = 3 _
    9.                       Select b
    10.  
    11.  
    12.         'function syntax
    13.         Dim matches2 = lst.Where(Function(b As Button) b.Tag IsNot Nothing _
    14.                                       AndAlso TypeOf b.Tag Is TreeView _
    15.                                       AndAlso DirectCast(b.Tag, TreeView).Nodes.Count = 3)
    (Disclaimer: perhaps the two are not exactly the same, because I never use function syntax it might contain some error)


    What I'm trying to say is: in the end, it won't matter one bit which method you use.

  25. #25

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Thanks for the Linq syntax examples Nick. I think the comparison will clarify a few things that have been puzzling me.

    Quote Originally Posted by NickThissen View Post
    What I'm trying to say is: in the end, it won't matter one bit which method you use.
    I believe you. In fact I started off using nested For loops but kept getting in a mess; the logic was more difficult than I expected. That's what made me decide to take a fresh look at the List extension methods, inline functions etc. And now that looks like a viable approach.

    I don't think performance in processing the lists will be all that crucial in this application anyway. The big time consumer is getting and generating the thumbnails. At the moment, I do that every time I visit a folder, but obviously I can speed it up drastically by caching the thumbnails.

    bye, BB

  26. #26
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: Can someone help me with a List comparison?

    Quote Originally Posted by boops boops View Post
    Thanks again VBDT. Probably it's clear I'm trying to make an image browser. At present each IB_Thumbnail contains a FileInfo and a thumbnail image. When I visit a folder the program generates the thumbnails for all the images it finds there. But that can take time, so I want to cache the IB_Thumbnails and just check the folder for changes. That's why I want to compare FileInfos in the cached thumbnails with those in the folder.

    I can't use generic List.Contains because the cached FileInfos will never be the same objects as the FileInfos read from disk -- even when they refer to the same images. Nick's custom Contains function (post #2) presents a feasible alternative. Clearly it depends on having an implementation of FileInfo.Equals: an IEqualityComparer such as the one you posted. That and Paul's solution, both of which use Linq, will probably work very well.

    The reason I am hanging out for something else is that I am trying to learn more about the possibilities of generics, and I don't want to take Linq on board for the moment. Surely something must be lurking among all the native methods and extensions of the Generic List? Taking a fresh trawl through msdn today, for example, I noticed that List(Of T).ConvertAll(Of TOutput) could be a way to turn the list of thumbnails into a list of FileInfos. That may turn out to be the way to go.

    Instead I could try to work something out using nested For loops. But I get the impression that Microsoft's newer methods will be more efficient as well as neater.

    BB
    Understood, it is much clear now what you want to do. Sometime ago I have done something like that creating windows browser that was listing all the files with their associated icons. So this is something similar what you are doing. Yes I remember doing the same way as you are trying to do, keep the created objects that have been already created and show them when I visited to the same folder. The way you are doing is different what I have done and requires these steps:

    1. No matter what, you will loop through all images in the folder since there might be added some new ones.
    2. Some images could be deleted after the last catch so you need to delete the corresponding thumbnail object.
    3. Some images could be changed after the last catch so the image that the object contains needs to be updated.

    The way I was doing was this: I had a DirectoryWatcher component (it is in the VS toolbar) that was watching all the folders that I have visited and have the cached data. So when a file was added, deleted or changed the corresponding object was changed accordingly. For example: if file was added than I created the object, if the file was deleted I deleted the object and if the file was changed I updated the object. As you can see this way you are not going through and checking all the objects. Also you won’t have the headache of adding and deleting thumbnails. In this way you are dealing with one thumbnail at the time, not looping throw all the files each time you visit the folder.

    I thought this approach can be an alternative to what you have now

  27. #27

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Can someone help me with a List comparison?

    Yes, it would be interesting to try a DirectoryWatcher. It shouldn't be too difficult to let it trigger a directory refresh in the same way as the user clicking on a TreeView node. And it ought to be possible to suppress the triggering when it might interfere with other processes. I am already using a BackgroundWorker to generate thumbnails from large images, which might prove useful in this connection too.

    Regards, BB

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width