当我尝试使用.NET 2.0从List中删除重复项时,我无法获得预期的结果。
List<Student> list1 = new List<Student>();
Student s = new Student();
s.Age = "35";
s.Name = "Nazmul";
list1.Add(s);
s = new Student();
s.Age = "35";
s.Name = "Nazmul";
list1.Add(s);
s = new Student();
s.Age = "35";
s.Name = "Nazmul";
list1.Add(s);
s = new Student();
s.Age = "35";
s.Name = "Nazmul";
list1.Add(s);
IComparer<Student> compare = new MyOrderingClass();
list1.Sort(compare);
Int32 index = 0;
while (index < list1.Count - 1)
{
if (list1[index].Equals(list1[index + 1]))
{
list1.RemoveAt(index);
}
else
{
index++;
}
}
foreach (Student st in list1)
{
Response.Write("Name:" + st.Name);
Response.Write("Age:" + st.Age + "<br/>");
}
上面使用的类和方法如下:
public class Student
{
private String name;
private String age;
public String Name
{
get { return name; }
set { name = value; }
}
public String Age {
get { return age; }
set { age = value; }
}
}
public class MyOrderingClass : IComparer<Student>
{
public int Compare(Student x, Student y)
{
int compareName = x.Name.CompareTo(y.Name);
if (compareName == 0)
{
return x.Age.CompareTo(y.Age);
}
return compareName;
}
}
我将所有列表项作为输出。想知道我在哪里做错了。
答案 0 :(得分:2)
您正在查看的核心思想可以通过操作来描述 - 相等 - 以及数据结构 - 集合。
首先,操作。
你的班级MyOrderingClass
已接近你想要的了。您可以使用IComparer<Student>
代替IEqualityComparer<Student>
,它提供了一种方法来确定两个实例是否相等。确定这一点需要两种方法:Equals
当然,GetHashCode
是一种&#34;快捷方式&#34;某些数据结构使用的方法,以查看实例是否可能相等。这里需要注意的重要一点是GetHashCode
的实现涉及用于确定相等的相同值。
public class MyOrderingClass : IEqualityComparer<Student>, IComparer<Student>
{
public int Compare(Student x, Student y)
{
if (ReferenceEquals(x, y))
{
return 0;
}
if (ReferenceEquals(x, null))
{
throw new ArgumentException("x");
}
if (ReferenceEquals(y, null))
{
throw new ArgumentException("y");
}
// Optional: use StringComparer.CurrentCultureIgnoreCase.CompareTo or maybe others
// from http://msdn.microsoft.com/en-us/library/system.stringcomparer.aspx
int compareName = x.Name.CompareTo(y.Name);
if (compareName == 0)
{
return x.Age.CompareTo(y.Age);
}
return compareName;
}
public int GetHashCode(Student student)
{
if(student == null)
{
throw new ArgumentNullException("student");
}
unchecked
{
return (student.Name ?? String.Empty).GetHashCode() ^ student.Age;
}
}
public bool Equals(Student x, Student y)
{
return Compare(x, y) == 0;
}
}
第二,数据结构。
使用Distinct
扩展方法可以实现拥有不同对象集合的想法,但查看ISet<T>
- HashSet<T>
的实现可能会有所帮助。这样做的原因是&#34;不同元素的概念&#34;实际上是一个集合概念的定义 - 属于一起的独特元素。 HashSet<T>
使用IEqualityComparer<T>
的实例 - 默认情况下,它使用EqualityComparer<T>.Default
来执行引用相等。当然,您可以提供自己的,例如新增强的MyOrderingClass
。事实证明,Distinct
方法使用基于散列的集合来跟踪它已经看到和产生的元素,并且为此它可以采用它通过的IEqualityComparer<T>
的实例。到这个内部集合。
现在我们已经检查了基本概念,让我们看看代码:
List<Student> list1 = new List<Student>();
// ... add instances with the same name and age
// option 1: use HashSet<T>
var set = new HashSet<Student>(list1, new MyOrderingClass());
Assert.Equal(1, set.Count);
// option 2: use Distinct
var distinct = list1.Distinct(new MyOrderingClass());
Assert.Equal(1, distinct.Count());
// option 3: when you don't have a proper set (e.g. .Net 2.0)
Dictionary<Student, Object> d = new Dictionary<Student, Object>(new MyOrderingClass());
list1.ForEach(delegate(Student e) { d[e] = null; });
Assert.Equal(1, d.Count);
答案 1 :(得分:2)
在.NET 2.0中,您可以使用Dictionary<>
类来获取不同的值。使用开箱即用功能可能是最有效的方法。显然在.NET 3.5及更高版本中使用Distinct
扩展方法。在这里,我添加了.NET 2.0实现。
public class Student : IEquatable<Student>
{
private String name;
private String age;
public String Name
{
get { return name; }
set { name = value; }
}
public String Age
{
get { return age; }
set { age = value; }
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + ((Age == null) ? 0 : Age.GetHashCode());
hash = hash * 23 + ((Name == null) ? 0 : Name.GetHashCode());
return hash;
}
}
public bool Equals(Student other)
{
if (other == null)
{
return false;
}
return Age == other.Age && Name == other.Name;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(Student)) return false;
return Equals((Student)obj);
}
}
Dictionary<Student, bool> dict = new Dictionary<Student, bool>();
foreach (Student student in list1)
{
if (!dict.ContainsKey(student))
{
dict.Add(student, false);
}
}
ICollection<Student> distinctList = dict.Keys;
答案 2 :(得分:1)
pmtamal提到:默认等于仅支持引用相等。这可能有用http://msdn.microsoft.com/en-US/library/bsc2ak47(v=vs.80).aspx
public class Student
{
private String name;
private String age;
public String Name
{
get { return name; }
set { name = value; }
}
public String Age
{
get { return age; }
set { age = value; }
}
public override bool Equals(object obj)
{
Student st = obj as Student;
if(st != null ){
return (this.name.Trim().ToLower().Equals(st.name.Trim().ToLower()) && this.age == st.age);
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}