Dav*_*.ca 28 c# linq lambda .net-3.5
我有一个这样的课:
class MyClass<T> {
public string value1 { get; set; }
public T objT { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
以及这个班级的清单.我想使用.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);
}
Run Code Online (Sandbox Code Playgroud)
lambda或LINQ的做法是什么?
jpb*_*chi 59
这两个马克的和dahlbyk的答案似乎很好地工作.我有一个更简单的解决方案.Distinct您可以使用,而不是使用GroupBy.它是这样的:
var listDistinct
= list.GroupBy(
i => i.value1,
(key, group) => group.First()
).ToArray();
Run Code Online (Sandbox Code Playgroud)
请注意,我已经将两个函数传递给了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 },
};
Run Code Online (Sandbox Code Playgroud)
结果是:
//{ value1 = ABC, objT = 0 }
//{ value1 = 123, objT = 2 }
//{ value1 = FOO, objT = 4 }
//{ value1 = BAR, objT = 5 }
//{ value1 = UGH, objT = 8 }
Run Code Online (Sandbox Code Playgroud)
我还没有测试它的性能.我相信这个解决方案可能比使用的解决方案慢一点Distinct.尽管有这个缺点,但有两个很大的优点:简单和灵活.通常,最好是简单优于优化,但这实际上取决于您尝试解决的问题.
嗯......我可能会写一个习惯,IEqualityComparer<T>以便我可以使用:
var listDistinct = list.Distinct(comparer).ToList();
Run Code Online (Sandbox Code Playgroud)
并通过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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用实用方法:
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
64303 次 |
| 最近记录: |