我正在尝试查找包含 2 个或更多区域成员的所有区域,其中搜索词是字符串值。这是我的代码。在 FindCommmonZones 方法中,当我尝试将 Intersect 的结果转换为 ObservableCollection 时,我得到了一个无效转换的运行时。问题是,有没有更好的方法来做到这一点?作为 FindCommonZones() 参数的字符串数组可以是任意数量的字符串。 StackOverflow 有一些其他类似的帖子,但没有一个真正回答我的问题 - 看起来它们都更多地与 SQL 相关。
部分代码:
public class Zone
{
public List<ZoneMember> MembersList = new List<ZoneMember>();
private string _ZoneName;
public string zoneName{ get{return _ZoneName;} set{_ZoneName=value;} }
public Zone ContainsMember(string member)
{
var contained = this.MembersList.FirstOrDefault(m => m.MemberWWPN.
Contains(member) || m.MemberAlias.Contains(member));
if (contained != null) { return this; }
else { return null; }
}
}
public class ZoneMember
// a zone member is a member of a zone
// zones have ports, WWPNs, aliases or all 3
{
private string _Alias = string.Empty;
public string MemberAlias {get{return _Alias;} set{_Alias = value; } }
private FCPort _Port = null;
public FCPort MemberPort { get { return _Port; } set { _Port = value; } }
private string _WWPN = string.Empty;
public string MemberWWPN { get { return _WWPN; } set { _WWPN = value; } }
private bool _IsLoggedIn;
public bool IsLoggedIn { get { return _IsLoggedIn; } set { _IsLoggedIn = value; } }
private string _FCID;
public string FCID {get{return _FCID;} set{ _FCID=value; } }
}
private ObservableCollection<ZoneResult> FindCommonZones(string[] searchterms)
{
ObservableCollection<ZoneResult> tempcollection =
new ObservableCollection<ZoneResult>();
//find the zones for the first search term
tempcollection = this.FindZones(searchterms[0]);
//now search for the rest of the search terms and compare
//them to existing result
for (int i = 1; i < searchterms.Count(); i++ )
{
// this line gives an exception trying to cast
tempcollection = (ObservableCollection<ZoneResult>)tempcollection.
Intersect(this.FindZones(searchterms[i]));
}
return tempcollection;
}
private ObservableCollection<ZoneResult> FindZones(string searchterm)
// we need to track the vsan where the zone member is found
// so use a foreach to keep track
{
ObservableCollection<ZoneResult> zonecollection = new ObservableCollection<ZoneResult>();
foreach (KeyValuePair<int, Dictionary<int, CiscoVSAN>> fabricpair in this.FabricDictionary)
{
foreach (KeyValuePair<int, CiscoVSAN> vsanpair in fabricpair.Value)
{
var selection = vsanpair.Value.ActiveZoneset.
ZoneList.Select(z => z.ContainsMember(searchterm)).
Where(m => m != null).OrderBy(z => z.zoneName);
if (selection.Count() > 0)
{
foreach (Zone zone in selection)
{
foreach (ZoneMember zm in zone.MembersList)
{
ZoneResult zr = new ZoneResult(zone.zoneName,
zm.MemberWWPN, zm.MemberAlias, vsanpair.Key.ToString());
zonecollection.Add(zr);
}
}
}
}
}
return zonecollection;
}
最佳答案
Intersect
实际上是 Enumerable.Intersect
并返回 IEnumerable<ZoneResult>
.这不是 ObservableCollection 的可转换,因为它不是一个 - 它是两个集合中相交元素的枚举。
不过,您可以从枚举中创建一个新 ObservableCollection:
tempcollection = new ObservableCollection<ZoneResult>(tempcollection
.Intersect(this.FindZones(searchterms[i]));
取决于你有多少元素,如何ZoneResult.Equals
已实现,以及您期望有多少搜索词,此实现可能可行也可能不可行(乍一看,FindZones
确实似乎有点过于复杂,复杂度为 O(n^4))。如果它看起来是资源消耗或瓶颈,那么就该进行优化了;否则,如果它有效,我就不会管它。
一个建议的优化可能如下(结合@Keith 将 ContainsMember
更改为 bool 的建议)——尽管它未经测试,但我的 SelectManys 可能有误,而且它实际上在很大程度上是相同的,你希望得到想法:
private ObservableCollection<ZoneResult> FindCommonZones(string[] searchterms)
{
var query = this.FabricDictionary.SelectMany(fabricpair =>
fabricpair.Value.SelectMany(vsanpair =>
vsanpair.Value.ActiveZoneSet.ZoneList
.Where(z=>searchterms.Any(term=>z.ContainsMember(term)))
.SelectMany(zone =>
zone.MembersList.Select(zm=>new ZoneResult(zone.zoneName, zm.MemberWWPN, zm.MemberAlias, vsanpair.Key.ToString()))
)
)
.Distinct()
.OrderBy(zr=>zr.zoneName);
return new ObservableCollection<ZoneResult>(query);
}
关于c# - 如何检查包含多个值的 CONTAINS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12676921/