我有一个C#应用程序,我希望从List
项目对象获取另一个包含不同对象的List。
我试过这个
List<Project> model = notre_admin.Get_List_Project_By_Expert(u.Id_user);
if (model != null) model = model.Distinct().ToList();
列表模型仍包含4个相同的对象Project
。
这是什么原因?我该如何解决?
答案 0 :(得分:12)
您需要在此处定义“相同”。我猜你的意思是“拥有相同的内容”,但不是类的默认定义:默认定义是“是同一个实例”。
如果您希望“相同”表示“具有相同的内容”,则有两种选择:
IEqualityComparer<Project>
)并将其作为参数提供给Distinct
Equals
GetHashCode
和Project
还有一些自定义方法,例如DistinctBy
,它们可用于许多地方,如果可以通过单个属性(通常为Id
)确定标识,则这种方法很有用 - 但不是在BCL中。但是例如:
if (model != null) model = model.DistinctBy(x => x.Id).ToList();
例如:
public static IEnumerable<TItem>
DistinctBy<TItem, TValue>(this IEnumerable<TItem> items,
Func<TItem, TValue> selector)
{
var uniques = new HashSet<TValue>();
foreach(var item in items)
{
if(uniques.Add(selector(item))) yield return item;
}
}
答案 1 :(得分:6)
var newList =
(
from x in model
select new {Id_user= x.Id_user}
).Distinct();
或者你可以像这样写
var list1 = model.DistinctBy(x=> x.Id_user);
答案 2 :(得分:5)
你如何定义相同的?您应该使用此定义覆盖Equals
中的Project
(如果您覆盖Equals
也覆盖GetHashCode
)。例如:
public class Project
{
public int ProjectID { get; set; }
public override bool Equals(object obj)
{
var p2 = obj as Project;
if (p2 == null) return false;
return this.ProjectID == m2.ProjectID;
}
public override int GetHashCode()
{
return ProjectID;
}
}
否则您只是检查reference equality。
答案 3 :(得分:4)
对象的引用不相等。如果您希望能够在整个对象本身而不仅仅是属性上执行此操作,则必须实现IEqualityComparer或IEquatable&lt; T&gt;。
答案 4 :(得分:3)
选中此示例:您需要使用Comparator或覆盖Equals()
class Program
{
static void Main( string[] args )
{
List<Item> items = new List<Item>();
items.Add( new Item( "A" ) );
items.Add( new Item( "A" ) );
items.Add( new Item( "B" ) );
items.Add( new Item( "C" ) );
items = items.Distinct().ToList();
}
}
public class Item
{
string Name { get; set; }
public Item( string name )
{
Name = name;
}
public override bool Equals( object obj )
{
return Name.Equals((obj as Item).Name);
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
答案 5 :(得分:3)
答案 6 :(得分:0)
使用下面显示的方法之一是不是更简单:)? 您可以通过某个键对域对象进行分组,然后选择FirstOrDefault,如下所示。
更有趣的选择是创建一些Comparer适配器,它接收域对象并创建Comparer可以使用/开箱即用的其他对象。基于比较器,您可以创建自定义linq扩展,如下面的示例所示。希望它有所帮助:)
[TestMethod]
public void CustomDistinctTest()
{
// Generate some sample of domain objects
var listOfDomainObjects = Enumerable
.Range(10, 10)
.SelectMany(x =>
Enumerable
.Range(15, 10)
.Select(y => new SomeClass { SomeText = x.ToString(), SomeInt = x + y }))
.ToList();
var uniqueStringsByUsingGroupBy = listOfDomainObjects
.GroupBy(x => x.SomeText)
.Select(x => x.FirstOrDefault())
.ToList();
var uniqueStringsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeText).ToList();
var uniqueIntsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeInt).ToList();
var uniqueStrings = listOfDomainObjects
.Distinct(new EqualityComparerAdapter<SomeClass, string>(x => x.SomeText))
.OrderBy(x=>x.SomeText)
.ToList();
var uniqueInts = listOfDomainObjects
.Distinct(new EqualityComparerAdapter<SomeClass, int>(x => x.SomeInt))
.OrderBy(x => x.SomeInt)
.ToList();
}
自定义比较器适配器:
public class EqualityComparerAdapter<T, V> : EqualityComparer<T>
where V : IEquatable<V>
{
private Func<T, V> _valueAdapter;
public EqualityComparerAdapter(Func<T, V> valueAdapter)
{
_valueAdapter = valueAdapter;
}
public override bool Equals(T x, T y)
{
return _valueAdapter(x).Equals(_valueAdapter(y));
}
public override int GetHashCode(T obj)
{
return _valueAdapter(obj).GetHashCode();
}
}
自定义linq扩展(DistinctBy扩展方法的定义):
// Embedd this class in some specific custom namespace
public static class DistByExt
{
public static IEnumerable<T> DistinctBy<T,V>(this IEnumerable<T> enumerator,Func<T,V> valueAdapter)
where V : IEquatable<V>
{
return enumerator.Distinct(new EqualityComparerAdapter<T, V>(valueAdapter));
}
}
测试用例中使用的域对象的定义:
public class SomeClass
{
public string SomeText { get; set; }
public int SomeInt { get; set; }
}
答案 7 :(得分:0)
List<ViewClReceive> passData = (List<ViewClReceive>)TempData["passData_Select_BankName_List"];
passData = passData?.DistinctBy(b=>b.BankNm).ToList();
它会起作用......