我有两个ArrayList数组。
public class ProductDetails
{
public string id;
public string description;
public float rate;
}
ArrayList products1 = new ArrayList();
ArrayList products2 = new ArrayList();
ArrayList duplicateProducts = new ArrayList();
现在我想要的是让所有产品(包含ProductDetails类的所有字段)在products1
和products2
中都有重复的描述。
我可以像传统方式一样运行两个for / while循环,但如果我在两个数组中拥有超过10k个元素,这将非常慢。
所以可能用LINQ做了一些事情。
答案 0 :(得分:1)
如果你想使用linQ,你需要编写自己的EqualityComparer,你可以覆盖两个方法 Equals 和 GetHashCode()
public class ProductDetails
{
public string id {get; set;}
public string description {get; set;}
public float rate {get; set;}
}
public class ProductComparer : IEqualityComparer<ProductDetails>
{
public bool Equals(ProductDetails x, ProductDetails y)
{
//Check whether the objects are the same object.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether the products' properties are equal.
return x != null && y != null && x.id.Equals(y.id) && x.description.Equals(y.description);
}
public int GetHashCode(ProductDetails obj)
{
//Get hash code for the description field if it is not null.
int hashProductDesc = obj.description == null ? 0 : obj.description.GetHashCode();
//Get hash code for the idfield.
int hashProductId = obj.id.GetHashCode();
//Calculate the hash code for the product.
return hashProductDesc ^ hashProductId ;
}
}
现在,假设你有这个对象:
ProductDetails [] items1= { new ProductDetails { description= "aa", id= 9, rating=2.0f },
new ProductDetails { description= "b", id= 4, rating=2.0f} };
ProductDetails [] items= { new ProductDetails { description= "aa", id= 9, rating=1.0f },
new ProductDetails { description= "c", id= 12, rating=2.0f } };
IEnumerable<ProductDetails> duplicates =
items1.Intersect(items2, new ProductComparer());
答案 1 :(得分:0)
考虑重写 System.Object.Equals 方法。
public class ProductDetails
{
public string id;
public string description;
public float rate;
public override bool Equals(object obj)
{
if(obj is ProductDetails == null)
return false;
if(ReferenceEquals(obj,this))
return true;
ProductDetails p = (ProductDetails)obj;
return description == p.description;
}
}
过滤将如此简单:
var result = products1.Where(product=>products2.Contains(product));
编辑:
请考虑此实施不是最佳的。
此外 - 在您的问题的评论中已经提出您使用数据库 这样就可以优化性能 - 根据数据库实现 - 在任何情况下 - 开销都不是你的。
但是,您可以使用Dictionary或HashSet优化此代码:
重载 System.Object.GetHashCode 方法:
public override int GetHashCode()
{
return description.GetHashCode();
}
您现在可以执行此操作:
var hashSet = new HashSet<ProductDetails>(products1);
var result = products2.Where(product=>hashSet.Contains(product));
这将提高您的性能,因为查找成本更低。
答案 2 :(得分:-1)
10k元素没什么,但请确保使用正确的集合类型。 ArrayList
已被弃用,请使用List<ProductDetails>
。
下一步是为您的班级实施适当的Equals
和GetHashCode
覆盖。这里假设description
是关键,因为从重复的角度来看,你关心的是:
public class ProductDetails
{
public string id;
public string description;
public float rate;
public override bool Equals(object obj)
{
var p = obj as ProductDetails;
return ReferenceEquals(p, null) ? false : description == obj.description;
}
public override int GetHashCode() => description.GetHashCode();
}
现在我们有选择权。一种简单有效的方法是使用哈希集:
var set = new HashSet<ProductDetails>();
var products1 = new List<ProductDetails>(); // fill it
var products2 = new List<ProductDetails>(); // fill it
// shove everything in the first list in the set
foreach(var item in products1)
set.Add(item);
// and simply test the elements in the second set
foreach(var item in products2)
if(set.Contains(item))
{
// item.description was already used in products1, handle it here
}
这为您提供线性(O(n)
)时间复杂度,您可以获得最佳效果。