0

I have a class with one property of List<String> to hold a dynamic list of one or more string ids.

public class FieldCompareItem
{
    public List<string> Fields = new List<string>();

    public FieldCompareItem(string[] fields)
    {
        for (int i = 0; i < fields.Count(); i++)

            Fields.Add(fields[i]);
        }
    }
}

I'm trying to compare 2 lists to see if the string arrays match but it doesn't work. Basically, I want to do an A/B compare to get items that only exist in A, in B, and in both, something like this:

var listA = new List<FieldCompareItem>
        {
            new FieldCompareItem(new[] {"a1"}),
            new FieldCompareItem(new[] {"a2"}),
            new FieldCompareItem(new[] {"a3","001"})
        };

var listB = new List<FieldCompareItem>
        {
            new FieldCompareItem(new[] {"a2"}),
            new FieldCompareItem(new[] {"a3"}),
            new FieldCompareItem(new[] {"a3","001"}),
            new FieldCompareItem(new[] {"a4"}),
            new FieldCompareItem(new[] {"a5"})
        };

//exists in A only
var aOnly = listA.Except(listB).ToList();
//expect a1,a3

//exists in B only
var bOnly = listB.Except(listA).ToList(); 
//expect a4,a5

//exists in both - this may be used for update A>B or B>A
var inBoth = ?????
//expect a2

Because they are values within an array property it doesnt seem to find by criteria. any help appreciated

Milsnipsky
  • 51
  • 8
  • 3
    possible duplicate of [Intersect two list in C#](http://stackoverflow.com/questions/7187996/intersect-two-list-in-c-sharp) – Shaharyar Jun 20 '15 at 08:29
  • @mmvsbg Jood job. But you've skipped one more place to improve - the `List`. Without `\``s, symbols inside brackets `<>` are read as HTML tags - and are not shown. – Nick Volynkin Jun 20 '15 at 08:33
  • @Shaharyar He is not wanting to intersect two collections. He wants wants a result set that contains unique strings **only** found in `listA`, and not in `listb` – Johnathon Sullinger Jun 20 '15 at 08:34
  • @JohnathonSullinger **get items that only exist in A, in B, and in both** this line clearly explains OP wants to get **items only in A** and **items only in B** and **items are common in both A and B (that is actually intersection)**. – Shaharyar Jun 20 '15 at 08:40
  • Well then, I guess it's time to get my eyes checked. Thanks for the correction. – Johnathon Sullinger Jun 20 '15 at 08:41
  • @JohnathonSullinger I think now you can undo your downvote as well :) – Shaharyar Jun 20 '15 at 08:50
  • I can't unless the post is edited. I had already tried; to much time had passed for me to change it. – Johnathon Sullinger Jun 20 '15 at 10:26

1 Answers1

0

Create a comparer first:

public class FieldCompareItemComparer: IEqualityComparer<FieldCompareItem>
{
  public bool Equals(FieldCompareItem x, FieldCompareItem y)
  {
    var result = x.Fields.SequenceEqual(y.Fields);
    return result;
  }

  public int GetHashCode(FieldCompareItem obj)
  {
    return String.Concat(obj.Fields).GetHashCode();
  }
}

then use it like the following:

var comparer = new FieldCompareItemComparer();

// exists in A only
var aOnly = listA.Except(listB, comparer).ToList();

// exists in B only
var bOnly = listB.Except(listA, comparer).ToList();

// exists in both
var inBoth = listA.Intersect(listB, comparer).ToList();
ycsun
  • 1,825
  • 1
  • 13
  • 21
  • none of the answers above work, they both return 0 count when they should return 1 instead. also aOnly and bOnly both dont return the required counts. i think it might be necessary to implement iEquatable or iComparable or something so it can compare the inner string arrays correctly. – Milsnipsky Jun 21 '15 at 18:41
  • When I first saw your post you didn't specify the type of listA and listB, and I thought you meant List. Now that it is List, you indeed need an equality comparer. Please see my edited answer. – ycsun Jun 22 '15 at 02:52
  • thanks thats just what i was looking for. in regards to performance i'd be using this to compare lists which may have a few hundred thousand items sometimes more than a million. is this an efficient comparison method for large volumes? – Milsnipsky Jun 22 '15 at 09:08
  • Do you mean a million `FieldCompareItem`s, or a million `string`s in `FieldCompareItem.Fields`? – ycsun Jun 22 '15 at 09:20
  • a million FieldCompareItem items in array which may contain one or more string in the "Fields" array property. tried the comparer with multiple strings in the property doesnt seem to find matches but if there's only one string value it finds a match – Milsnipsky Jun 23 '15 at 18:48
  • If it's a million `FieldCompareItem` then the performance should be just find. The implementation of `Except` and `Intersect` is quite efficient. And what do you mean by "tried the comparer with multiple strings in the property doesnt seem to find matches but if there's only one string value it finds a match"? – ycsun Jun 24 '15 at 02:53
  • i tried the following where in some cases i'll need to compare against multiple keys. see the above code sample. the lists can contain something like: new FieldCompareItem(new[] {"a3","001"}) – Milsnipsky Jun 24 '15 at 07:53