基于阵列的LINQ +短路
本文关键字:LINQ 短路 阵列 于阵列 | 更新日期: 2023-09-27 18:16:44
我有一个简单的LINQ查询,我想短路,基于数组中的第一个匹配值。我只是想返回,基于xmlDoc匹配数组中的第一项的第一个值,例如,如果它匹配"B",那么它将退出,如果它不匹配,那么它将尝试匹配"C"等。
我当然可以手动遍历数组并验证值是否为NULL,这可能是我必须做的,但我一直在寻找是否有更优雅的方法来做到这一点。
许多谢谢,瑜珈
string[] searchTypes = { "B", "C", "D", "A" };
XDocument xDoc = XDocument.Parse(xmlString);
for (int i = 0; i < searchTypes.Length; i++)
commsValue = (from r in xDoc.Descendants("Root")
where r.Element("dCode") != null && r.Element("dCode").Value == searchTypes[i])
select r.Element("Number").Value).FirstOrDefault();
if (commsValue == null)
{
continue;
}
}
不,但是你可以让你的循环是一个xDoc.Descendants("Root")
的单循环(linq内部循环),并减少对数组的查找。
首先从searchTypes
创建一个查找字典:
var lookup = new [] { "B", "C", "D", "A" }
.Select((e, i) => new {Key = e, Index = i})
.ToDictionary(i => i.Key, i => i.Index);
现在"B"
有0
, "C"
有1
,等等。
现在对于实际的循环:
int curIndex = int.MaxValue;
foreach(var r in xDoc.Descendants("Root"))
{
int index;
if (r.Element("dCode") != null && lookup.TryGetValue(r.Element("dCode").Value, out index))
{
if (index == 0)
{
commsValue = r.Element("Number").Value;
break; // short-circuit
}
else if (index < curIndex)
{
commsValue = r.Element("Number").Value; // Value to have after finished loop.
curIndex = index;
}
}
}
据我所知,没有内置的短路方法。按照您的提问方式,它将在整个XML节点列表中搜索"B",如果没有找到,则在整个节点列表中搜索"C",等等。
如果没有更多的细节,很难给你一个好的答案。"B"被找到的频率是多少,XML文档有多少个节点?您可以遍历整个节点列表,跟踪最佳匹配,在找到第一个"B"时退出,或者在最后退出,然后返回最佳的非B结果。但是没有这样的内置LINQ方法存在,但是你可以构建自己的自定义方法。
public static XmlNode FindBestNode(this IEnumerable<XmlNode> nodes, string[] vals)
{
XmlNode best=null;
int bestindex=vals.length+1;
while(nodes.MoveNext())
{
var currindex=vals.indexOf(nodes.Current.Element("dCode").Value));
if (currindex>=0) {
if (currindex==0) return nodes.Current;
if (currindex<bestindex) {
bestindex=currindex;
best=nodes.Current;
}
}
return best;
}
我不是xml查询的专家,但是上面的应该是相当接近的。
使用:string[] searchTypes = { "B", "C", "D", "A" };
XDocument xDoc = XDocument.Parse(xmlString);
var bestNode=xDoc.Descendants("Root")
.Where(r=>r.Element("dCode")!=null)
.FindBestNode(searchTypes);
您可以使用在连接中保留第一个集合的排序顺序这一事实。所以把serachTypes
和xDoc.Descendants("Root")
连接起来,取第一个元素:
string[] searchTypes = { "B", "C", "D", "A" };
XDocument xDoc = XDocument.Parse(xmlString);
var commsValue = (from st in searchTypes
join r in xDoc.Descendants("Root")
on st equals r.Element("dCode").Value
where r.Element("dCode") != null)
.FirstOrDefault();