所以我有两个列表。
List<Farmer> CSVFarmer;
List<Farmer> Farmers;
CSVFarmer List从一个读取csv文件的方法中获取其项目。
Farmers List从sql数据库中的表中获取其项目;
现在我要做的是比较两个列表并返回一个非匹配项列表;
例如,如果List CSVFarmer具有:
FarmerName ContractNumber ContactNumber
John 2468 12345
Mike 13579 15790
列表农民有:
FarmerName ContractNumber ContactNumber
Mike 13579 15790
返回的列表中只应包含一个项目:Farmer John。 农民阶层:
public class Farmer:INotifyPropertyChanged
{
int _id;
string _firstName;
string _farmerNo;
string _contactNumber;
public Farmer()
{
_firstName = string.Empty;
_farmerNo = string.Empty;
_contactNumber = string.Empty;
}
public int Id
{
get { return _id; }
set
{
_id = value;
OnPropertyChanged("Id");
}
}
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
public string FarmerNo
{
get { return _farmerNo; }
set
{
_farmerNo = value;
OnPropertyChanged("FarmerNo");
}
}
public string ContactNumber
{
get { return _contactNumber; }
set
{
_contactNumber = value;
OnPropertyChanged("ContactNumber");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged (string property)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
我试过这个:
public class vmUserManagement
{
public List<Farmer> Farmer { get; set; }
public List<Farmer> CSVFarmers { get; set; }
public List<Farmer> Farmers { get; set; }
public vmUserManagement()
{
CSVFarmers = new List<Farmer>();
Farmers = new List<Farmer>();
Farmer = new List<Farmer>();
}
public List<Farmer> getAllFarmers()
{
Farmers = RepoDapper.getAllFarmers();
return Farmers;
}
public List<Farmer> CSVImportFarmer()
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.DefaultExt = ".csv";
openFile.Filter = "(.csv) | *.csv";
var browseFile = openFile.ShowDialog();
if (browseFile == true)
{
string FilePath = openFile.FileName;
List<Farmer> values = File.ReadAllLines(FilePath).Select(v => FromFarmerCsv(v)).ToList();
CSVFarmers = values;
}
return CSVFarmers;
}
public static Farmer FromFarmerCsv(string csvLine)
{
string[] values = csvLine.Split(',');
Farmer farmer = new Farmer();
farmer.FirstName = values[0];
farmer.FarmerNo = values[1];
farmer.ContactNumber = values[2];
return farmer;
}
public List<Farmer> validateFarmerList()
{
foreach (var a in CSVFarmers)
{
foreach (var b in Farmers)
{
if (a != b)
{
Farmer.Add(a);
}
}
}
return Farmer;
}
}
我遇到的问题是我最终会在List Farmer中输入两个条目。都是农夫约翰和农夫麦克。当我只得到一个包含Farmer John的List时。那是为什么?
我也尝试使用过:
public List<Farmer> validateFarmerList()
{
Farmer = CSVFarmers.Except(Farmers).ToList();
return Farmer;
}
但我仍然在我的农夫名单中找到两个项目(农夫约翰和迈克),而不是一个。 我错过了什么吗?任何帮助将不胜感激。
答案 0 :(得分:3)
您未在dash (-)
课程中覆盖Equals
和GethashCode
。这就是为什么Farmer
无法正常工作以及(a != b)
失败的原因相同:仅引用进行比较且两者都是不同的实例。
.NET应该如何知道农民的Enumerable.Except
与识别他有关?一个方法是通过覆盖ContractNumber
和Equals
:
GetHashCode
现在您可以使用public class Farmer : IEquatable<Farmer>
{
public string FarmerName { get; set; }
public string ContractNumber { get; set; }
// .... other properties etc
public bool Equals(Farmer other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return string.Equals(ContractNumber, other.ContractNumber);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Farmer) obj);
}
public override int GetHashCode()
{
return (ContractNumber != null ? ContractNumber.GetHashCode() : 0);
}
}
:
Except
第二种方法是实施自定义Farmer = CSVFarmers.Except(Farmers).ToList();
,如果您无法更改IEqualityComparer<Farmer>
类本身,或者您不想改变它的行为,只想要一个自定义比较器:
Farmer
您可以在许多LINQ方法中使用此比较器,例如也可以在public class FarmerContractComparer : IEqualityComparer<Farmer>
{
public bool Equals(Farmer x, Farmer y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(null, x) || ReferenceEquals(null, y)) return false;
return x.ContractNumber == y.ContractNumber;
}
public int GetHashCode(Farmer obj)
{
return (obj.ContractNumber != null ? obj.ContractNumber.GetHashCode() : 0);
}
}public class FarmerContractComparer : IEqualityComparer<Farmer>
{
public bool Equals(Farmer x, Farmer y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(null, x) || ReferenceEquals(null, y)) return false;
return x.ContractNumber == y.ContractNumber;
}
public int GetHashCode(Farmer obj)
{
return (obj.ContractNumber != null ? obj.ContractNumber.GetHashCode() : 0);
}
}
:
Enumerable.Except
这种方法的优点是可以为不同的任务提供不同的比较器。
第三种方法:使用LINQ并且不要创建新类(减少可重用性和效率,但减少工作量):
Farmer = CSVFarmers.Except(Farmers, new FarmerContractComparer()).ToList();
答案 1 :(得分:0)
您需要创建一个实现IEqualityComparer<Farmer>
的类,并将其实例作为第二个参数传递给您的农民.Except()
或实施IEquatable<Farmer>
类。
另一个答案已经很好地实施了后者。如果总是希望农民在合同编号相等时保持平等,那就使用那个。
因此,如果您希望您的Except适用于合同号码,但在其他地方您需要其他条件,则需要第一个选项:
class FarmerEqualWhenContractEqualComparer : IEqualityComparer<Farmer>
{
public bool Equals(Farmer x, Farmer y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the farmers' contracts are equal.
return x.ContractNumber == y.ContractNumber;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Farmer farmer)
{
//Check whether the object is null
if (Object.ReferenceEquals(product, null)) return 0;
//Get hash code for the Name field if it is not null.
return farmer.ContractNumber?.GetHashCode() ?? 0;
}
}
然后你可以这样做:
var changedOrNew = CSVFarmers.Except(Farmers, new FarmerEqualWhenContractEqualComparer()).ToList();