将两个对象列表与多个值相交
intersect two lists of objects on multiple values
假设我有两个相同的列表 class。
public class emailfilter
{
public string from {get;set;}
public string to {get;set;}
public string cc {get;set;}
public string subj {get;set;}
public string body {get;set;}
public string emailid {get;set;}
}
//there are two lists of type emailfilter. 1 list is formed dynamically from the config file
List<emailfilter> configfilterlist = //mock sudo code//
{
efilter tempobj = new efilter();
tempobj.from = config.from or "" if no value
tempobj.to = config.to or "" if no value
tempobj.cc = config.cc or "" if no value
tempobj.subj = config.subj or "" if no value
tempobj.body = config.body or "" if no value
configfilterlist.add(tempobj);
}
//List1 will never have an emailID
//List2 is formed from email items pulled from exchange and made into efilter objects and those do have an emailid.
//List2 will typically have all object fields populated. List1, the object fields are optional
所以我想 compare/intersect 将针对电子邮件项目列表 2 的筛选项目列表 1 合并为一个没有重复项的组合列表,该列表仅包含具有列表 1 的所有筛选条件并包含列表 2 的 mailid 的项目。
如果 List1 上的值没有值,我想忽略它并只匹配跳过任何 "" 空白字符串提供的配置值。我希望有一种方法可以用 lambda 和 linq 做到这一点,但我还没有看到任何比较多个值并忽略其他值的例子,比如在这种情况下 emailID。
更新:感谢@wertzui 提供解决此问题所需的答案。最终的解决方案只是略有不同,所以更新 post/question 本质上是最终的解决方案,以防它帮助另一个迷失的灵魂。
public class emailfilter: IEquatable<emailfilter>
{
public string from { get; set; }
public string to { get; set; }
public string cc { get; set; }
public string subj { get; set; }
public string body { get; set; }
public string emailid { get; set; }
public override int GetHashCode()
{
return System.HashCode.Combine(from, to, cc, subj, body);
}
public override bool Equals(object? obj) => Equals(obj as emailfilter);
public bool Equals(emailfilter? other)
{
return
other != null &&
(from.Contains(other.from) || other.from == "") &&
(to.Contains(other.sentto) || other.to == "") &&
(cc.Contains(other.cc) || other.cc == "") &&
(subj.Contains(other.subj) || other.subj == "") &&
(body.Contains(other.body) || other.body == "");
}
}
//emailsasfilters is List2 = all exchange emails as filter objects
var combinedSet = new HashSet<emailfilter>();
foreach (var filter in configfilterlist) //configfilterlist is List1 = filters from Config
{
if (emailsasfilters.Contains(filter))
combinedSet.Add(emailsasfilters.ElementAt(emailsasfilters.IndexOf(filter)));
}
combinedSet.Dump();
从 .Net 6 开始,您可以使用一种新的 UnionBy
方法。
var combined = configfilterlist
.UnionBy(
exchangefilterlist,
e => new { e.from, e.to, e.cc, e.subj, e.body })
.ToList();
另一种适用于旧框架版本的方法是,使用 HashSet<T>
并实现 GetHashCode
和 Equals
public class emailfilter: IEquatable<emailfilter>
{
public string from { get; set; }
public string to { get; set; }
public string cc { get; set; }
public string subj { get; set; }
public string body { get; set; }
public string emailid { get; set; }
public override int GetHashCode()
{
return System.HashCode.Combine(from, to, cc, subj, body);
}
public override bool Equals(object? obj) => Equals(obj as emailfilter);
public bool Equals(emailfilter? other)
{
return
other != null &&
from == other.from &&
to == other.to &&
cc == other.cc &&
subj == other.subj &&
body == other.body;
}
}
var combinedSet = new HashSet<emailfilter>(configfilterlist);
foreach (var email in exchangefilterlist)
{
combinedSet.Add(email);
}
combinedSet.Dump();
假设我有两个相同的列表 class。
public class emailfilter
{
public string from {get;set;}
public string to {get;set;}
public string cc {get;set;}
public string subj {get;set;}
public string body {get;set;}
public string emailid {get;set;}
}
//there are two lists of type emailfilter. 1 list is formed dynamically from the config file
List<emailfilter> configfilterlist = //mock sudo code//
{
efilter tempobj = new efilter();
tempobj.from = config.from or "" if no value
tempobj.to = config.to or "" if no value
tempobj.cc = config.cc or "" if no value
tempobj.subj = config.subj or "" if no value
tempobj.body = config.body or "" if no value
configfilterlist.add(tempobj);
}
//List1 will never have an emailID
//List2 is formed from email items pulled from exchange and made into efilter objects and those do have an emailid.
//List2 will typically have all object fields populated. List1, the object fields are optional
所以我想 compare/intersect 将针对电子邮件项目列表 2 的筛选项目列表 1 合并为一个没有重复项的组合列表,该列表仅包含具有列表 1 的所有筛选条件并包含列表 2 的 mailid 的项目。 如果 List1 上的值没有值,我想忽略它并只匹配跳过任何 "" 空白字符串提供的配置值。我希望有一种方法可以用 lambda 和 linq 做到这一点,但我还没有看到任何比较多个值并忽略其他值的例子,比如在这种情况下 emailID。
更新:感谢@wertzui 提供解决此问题所需的答案。最终的解决方案只是略有不同,所以更新 post/question 本质上是最终的解决方案,以防它帮助另一个迷失的灵魂。
public class emailfilter: IEquatable<emailfilter>
{
public string from { get; set; }
public string to { get; set; }
public string cc { get; set; }
public string subj { get; set; }
public string body { get; set; }
public string emailid { get; set; }
public override int GetHashCode()
{
return System.HashCode.Combine(from, to, cc, subj, body);
}
public override bool Equals(object? obj) => Equals(obj as emailfilter);
public bool Equals(emailfilter? other)
{
return
other != null &&
(from.Contains(other.from) || other.from == "") &&
(to.Contains(other.sentto) || other.to == "") &&
(cc.Contains(other.cc) || other.cc == "") &&
(subj.Contains(other.subj) || other.subj == "") &&
(body.Contains(other.body) || other.body == "");
}
}
//emailsasfilters is List2 = all exchange emails as filter objects
var combinedSet = new HashSet<emailfilter>();
foreach (var filter in configfilterlist) //configfilterlist is List1 = filters from Config
{
if (emailsasfilters.Contains(filter))
combinedSet.Add(emailsasfilters.ElementAt(emailsasfilters.IndexOf(filter)));
}
combinedSet.Dump();
从 .Net 6 开始,您可以使用一种新的 UnionBy
方法。
var combined = configfilterlist
.UnionBy(
exchangefilterlist,
e => new { e.from, e.to, e.cc, e.subj, e.body })
.ToList();
另一种适用于旧框架版本的方法是,使用 HashSet<T>
并实现 GetHashCode
和 Equals
public class emailfilter: IEquatable<emailfilter>
{
public string from { get; set; }
public string to { get; set; }
public string cc { get; set; }
public string subj { get; set; }
public string body { get; set; }
public string emailid { get; set; }
public override int GetHashCode()
{
return System.HashCode.Combine(from, to, cc, subj, body);
}
public override bool Equals(object? obj) => Equals(obj as emailfilter);
public bool Equals(emailfilter? other)
{
return
other != null &&
from == other.from &&
to == other.to &&
cc == other.cc &&
subj == other.subj &&
body == other.body;
}
}
var combinedSet = new HashSet<emailfilter>(configfilterlist);
foreach (var email in exchangefilterlist)
{
combinedSet.Add(email);
}
combinedSet.Dump();