views:

90

answers:

3

When I use the following code I get the same items multiple times.

XElement neededFiles = new XElement("needed",
    from o in _9nFiles.Elements()
    join t in addedToSitePull.Elements()
         on o.Value equals
         t.Value
    where o.Value == t.Value
    select new XElement("pic", o.Value));

I'd like to get only unique items.

I saw a post here that used and I tried to implement it, but the change had no affect

the post: http://stackoverflow.com/questions/3519165/how-can-i-do-select-unique-with-linq

The code:

XElement neededFiles = new XElement("needed",
(from o in _9nFiles.Elements()
join t in addedToSitePull.Elements()
on o.Value equals
 t.Value
 where o.Value == t.Value
select new XElement("pic", o.Value)).Distinct() );

Thanks Asaf

+4  A: 

I imagine the reason this doesn't work is because XElement.Equals uses a simple reference equality check rather than comparing the Value properties of the two items. If you want to compare the values, you could change it to:

_9nfiles.Elements()
    .Join(addedToSitePull, o => o.Value, t => t.Value, (o, t) => o.Value)
    .Distinct()
    .Select(val => new XElement("pic", val));

You could also create your own IEqualityComparer<T> for comparing two XElements by their values. Note this assumes all values are non-null:

public class XElementValueEqualityComparer : IEqualityComparer<XElement>
{
    public bool Equals(XElement x, XElement y)
    {
        return x.Value.Equals(y.Value);
    }

    public int GetHashCode(XElement x)
    {
        return x.Value.GetHashCode();
    }
}

Then you could replace the existing call to Distinct with Distinct(new XElementValueEqualityComparer()).

Lee
+1 despite the fact that I had to implement a bad solution due to time issues ,I'm looking forward to test and learn your solution - thanks Asaf
Asaf
+3  A: 

Distinct doesn't work because XElements are compared by reference, not by value. The solution is to use another overload of Distinct - Distinct(IEqualityComparer);

You need to implement IEqualityComparer for example as follows:

class XElementEqualityComparer : IEqualityComparer<XElement>
    {
        #region IEqualityComparer<XElement> Members

        public bool Equals(XElement x, XElement y)
        {
            if (x == null ^ y == null)
                return false;

            if (x == null && y == null)
                return true;

            return x.Value == y.Value;
        }

        public int GetHashCode(XElement obj)
        {
            if (obj == null)
                return 0;

            return obj.Value.GetHashCode();
        }

        #endregion
    }
ILya
Lee's answer is better because it's more compact. I leave mine simply for example
ILya
+1 thanks for the unswer + the rare advice to use someone else solution.
Asaf
A: 

It's not a good solution - but really easy.

foreach (XElement  pic in neededFiles.Elements())
{
    unSyncedPictures.Add(pic.Value);
}
List<string> temp = new List<string>();
temp.AddRange(unSyncedPictures.Distinct());
Asaf