开发者

Select unique items with LINQ

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 Stack Overflow post, How can I do SELECT UNIQUE with LINQ?, that used it, and I tried to implement it, but the change had no affect.

The code:

XElement neededFiles = new XElement("needed",
(from 开发者_StackOverflow中文版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() );


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()).


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
    }


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());
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜