Dav*_*.ca 28 c# linq lambda .net-3.5
我有一个这样的课:
class MyClass<T> {
    public string value1 { get; set; }
    public T objT { get; set; }
}
以及这个班级的清单.我想使用.net 3.5 lambda或linq来获取不同value1的MyClass列表.我想这可能比在.net 2.0中缓存这样的列表的方式简单得多:
List<MyClass<T>> list; 
...
List<MyClass<T>> listDistinct = new List<MyClass<T>>();
foreach (MyClass<T> instance in list)
{
    // some code to check if listDistinct does contain obj with intance.Value1
    // then listDistinct.Add(instance);
}
lambda或LINQ的做法是什么?
jpb*_*chi 59
这两个马克的和dahlbyk的答案似乎很好地工作.我有一个更简单的解决方案.Distinct您可以使用,而不是使用GroupBy.它是这样的:
var listDistinct
    = list.GroupBy(
        i => i.value1,
        (key, group) => group.First()
    ).ToArray();
请注意,我已经将两个函数传递给了GroupBy().第一个是键选择器.第二个只从每个组中获得一个项目.从你的问题来看,我认为First()是正确的.如果你愿意,你可以写一个不同的.你可以尝试Last()看看我的意思.
我使用以下输入运行测试:
var list = new [] {
    new { value1 = "ABC", objT = 0 },
    new { value1 = "ABC", objT = 1 },
    new { value1 = "123", objT = 2 },
    new { value1 = "123", objT = 3 },
    new { value1 = "FOO", objT = 4 },
    new { value1 = "BAR", objT = 5 },
    new { value1 = "BAR", objT = 6 },
    new { value1 = "BAR", objT = 7 },
    new { value1 = "UGH", objT = 8 },
};
结果是:
//{ value1 = ABC, objT = 0 }
//{ value1 = 123, objT = 2 }
//{ value1 = FOO, objT = 4 }
//{ value1 = BAR, objT = 5 }
//{ value1 = UGH, objT = 8 }
我还没有测试它的性能.我相信这个解决方案可能比使用的解决方案慢一点Distinct.尽管有这个缺点,但有两个很大的优点:简单和灵活.通常,最好是简单优于优化,但这实际上取决于您尝试解决的问题.
嗯......我可能会写一个习惯,IEqualityComparer<T>以便我可以使用:
var listDistinct = list.Distinct(comparer).ToList();
并通过LINQ编写比较器....
可能有点矫枉过正,但可重复使用,至少:
用法优先:
static class Program {
    static void Main() {
        var data = new[] {
            new { Foo = 1,Bar = "a"}, new { Foo = 2,Bar = "b"}, new {Foo = 1, Bar = "c"}
        };
        foreach (var item in data.DistinctBy(x => x.Foo))
            Console.WriteLine(item.Bar);
        }
    }
}
用实用方法:
public static class ProjectionComparer
{
    public static IEnumerable<TSource> DistinctBy<TSource,TValue>(
        this IEnumerable<TSource> source,
        Func<TSource, TValue> selector)
    {
        var comparer = ProjectionComparer<TSource>.CompareBy<TValue>(
            selector, EqualityComparer<TValue>.Default);
        return new HashSet<TSource>(source, comparer);
    }
}
public static class ProjectionComparer<TSource>
{
    public static IEqualityComparer<TSource> CompareBy<TValue>(
        Func<TSource, TValue> selector)
    {
        return CompareBy<TValue>(selector, EqualityComparer<TValue>.Default);
    }
    public static IEqualityComparer<TSource> CompareBy<TValue>(
        Func<TSource, TValue> selector,
        IEqualityComparer<TValue> comparer)
    {
        return new ComparerImpl<TValue>(selector, comparer);
    }
    sealed class ComparerImpl<TValue> : IEqualityComparer<TSource>
    {
        private readonly Func<TSource, TValue> selector;
        private readonly IEqualityComparer<TValue> comparer;
        public ComparerImpl(
            Func<TSource, TValue> selector,
            IEqualityComparer<TValue> comparer)
        {
            if (selector == null) throw new ArgumentNullException("selector");
            if (comparer == null) throw new ArgumentNullException("comparer");
            this.selector = selector;
            this.comparer = comparer;
        }
        bool IEqualityComparer<TSource>.Equals(TSource x, TSource y)
        {
            if (x == null && y == null) return true;
            if (x == null || y == null) return false;
            return comparer.Equals(selector(x), selector(y));
        }
        int IEqualityComparer<TSource>.GetHashCode(TSource obj)
        {
            return obj == null ? 0 : comparer.GetHashCode(selector(obj));
        }
    }
}
| 归档时间: | 
 | 
| 查看次数: | 64303 次 | 
| 最近记录: |