none
Comparing two lists of different object types

    Domanda

  • I have two object collections, a SearchResultCollection and a ProfileBase[] collection.  SeachResultCollection can be made into a SearchResult, which contains a property of .Path (the distinguished name of the SearchResult).  Likewise, ProfileBase can be cased to a UserProfile, which contains a PropertyConstant.DistinguishedName value.

    I want to compare these two DNs as strings, and delete the UserProfile object if it doesn't exist within the SearchResultCollection.  How can I go about this?


    http://sharepoint.nauplius.net

    martedì 1 maggio 2012 03:50

Risposte

  • var query = mySearchResultCollection.Select(searchResult => searchResult.Path);
    HashSet<string> paths = new HashSet<string>(query);
    
    var profiles = userProfiles.Select(profile => new 
    {
     ShouldKeep = paths.Contains(getPathFromProfile(profile)),
     Profile = profile
    });
    
    foreach(var profile in profiles.Where(result => !result.ShouldKeep))
    {
      profile.Delete();
    }
    
    var profilesToKeep = profiles.Where(result => result.ShouldKeep);
    I'm not sure if by deleting a profile you mean just removing it from a collection, or making a collection with all of the profiles to keep, or if it meant performing a delete operation on the items that need to be deleted.  Since the latter is a bit more work I did that, you can remove the relevant section of code if that's not what you were looking for and it should still be fine.
    martedì 1 maggio 2012 15:43

Tutte le risposte

  • Hi, 

    You can do this like, 

    var matchedList = SearchResultCollection.Intersect(ProfileBaseCollection

    , new DNSEqualityComparer()); foreach (var item in matchedList) { SearchResultCollection.Remove(item); }

    ----------------------------------------------------

    class DNSEqualityComparer : IEqualityComparer
    {
    public bool Equals(object x, object y)
    {
    //Implement your logic over here
    }

    public int GetHashCode(object obj)
    {
    throw new NotImplementedException();
    }
    }

    Hope this helps you...


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".


    • Modificato Kris444 martedì 1 maggio 2012 05:14
    • Proposto come risposta Paw Jershauge martedì 1 maggio 2012 07:17
    martedì 1 maggio 2012 05:14
  • If I where you, i would make the ProfileBase[] array into a List<ProfileBase> then its easier to delete from.

    And when thats done, use the findall method on the List<ProfileBase> to find all the items that are in the SearchResultCollection.

    Else go with what Kris444 suggested. ;)

    Hope it helps


    With great code, comes great complexity, so keep it simple stupid...

    martedì 1 maggio 2012 07:21
  • Then serialize them both and compare them.

    Be aware this article is despite its name not about a clone in .Net terminology but about deep copies which for most collections can only be done with serialization.

    http://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c


    Success
    Cor

    martedì 1 maggio 2012 08:22
  • I think I'm still a bit lost in what I need to do, or at least comparing the properties that I need.

    So let's say I have ProfileBase[] pBase and SearchResultCollection searchRc.  I have to take both of those and convert them to access the properties I need:

    UserProfile uProfile = (UserProfile)pBase;

    uProfile[PropertyConstants.DistinguishedName].Value

    foreach(SearchResult sr in searchRc)

    {

    sr.Path

    }

    Then I need to compare each sr.Path in searchRc to each uProfile[PropertyConstants.DistinguishedName].Value in pBase and if a match is found, I'll keep the uProfile.  If no match for the uProfile is found within searchRc, delete the uProfile.


    http://sharepoint.nauplius.net


    martedì 1 maggio 2012 14:14
  • var query = mySearchResultCollection.Select(searchResult => searchResult.Path);
    HashSet<string> paths = new HashSet<string>(query);
    
    var profiles = userProfiles.Select(profile => new 
    {
     ShouldKeep = paths.Contains(getPathFromProfile(profile)),
     Profile = profile
    });
    
    foreach(var profile in profiles.Where(result => !result.ShouldKeep))
    {
      profile.Delete();
    }
    
    var profilesToKeep = profiles.Where(result => result.ShouldKeep);
    I'm not sure if by deleting a profile you mean just removing it from a collection, or making a collection with all of the profiles to keep, or if it meant performing a delete operation on the items that need to be deleted.  Since the latter is a bit more work I did that, you can remove the relevant section of code if that's not what you were looking for and it should still be fine.
    martedì 1 maggio 2012 15:43
  • Yep, I'm looking to delete the UserProfile object when the DistinguishedName is absent from the SearchResultCollection.

    However, while I have:

    SearchResultCollection users;
    List<SearchResultCollection> usersList = users.Cast<SearchResultCollection>().ToList();
    
    var query = usersList.Select(sr => sr.Path);

    "sr" just ends up being a SearchResultCollection, not a SearchResult, so it doesn't have a Path property.


    http://sharepoint.nauplius.net

    martedì 1 maggio 2012 16:21
  • Yep, I'm looking to delete the UserProfile object when the DistinguishedName is absent from the SearchResultCollection.

    However, while I have:

    SearchResultCollection users;
    List<SearchResultCollection> usersList = users.Cast<SearchResultCollection>().ToList();
    
    var query = usersList.Select(sr => sr.Path);

    "sr" just ends up being a SearchResultCollection, not a SearchResult, so it doesn't have a Path property.

    You're casting an IEnumerable of SearchResults into an IEnumerable of SearchResultCollections.

    Just remove the second line entirely, it shouldn't be there, or change the cast to be SearchResults or whatever the actual objects of the SearchResultCollection are.

    Finally, there's no reason to ToList a query when you're just going to perform a select on it; just leave the ToList off and change the variable types accordingly.
    martedì 1 maggio 2012 16:29
  • SearchResultCollection does not have a .Select method, though... In order to get the .Select, it needs to be cast ToList().

    http://msdn.microsoft.com/en-us/library/system.directoryservices.searchresultcollection_methods(v=vs.90).aspx

    What I, at least thought, I needed was to get a SearchResult, which does have the .Path property, out of my SearchResultCollection.


    http://sharepoint.nauplius.net

    martedì 1 maggio 2012 16:34
  • "SearchResultCollection does not have a .Select method, though... In order to get the .Select, it needs to be cast ToList()."

    No, it needs to be an IEnumerable<T>, not a List.  If SearchResultCollection doesn't implement IEnumerable<T> then you can use the Cast method, and you need to cast it to an IEnumerable of SearchResults, not SearchResultCollections as I said before.  Cast returns an IEnumerable<T>, so there is no need to call ToList after it.  In fact, ToList is a method of IEnumerable<T>, so anything that you can call ToList on, you can call Select on (by definition).

    "What I, at least thought, I needed was to get a SearchResult, which does have the .Path property, out of my SearchResultCollection."

    Which is why it's important to 'Cast' to the correct type, as I told you before.

    martedì 1 maggio 2012 16:44
  • And now I get it, thank you for your help servy42, and everyone else!

    http://sharepoint.nauplius.net

    martedì 1 maggio 2012 17:49