我有一个简单的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;
}
}
答案 0 :(得分:2)
不,但你可以让你的循环成为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;
}
}
}
,依此类推。
现在进行实际循环:
<div id=test_one contenteditable=true>
<div id=test_other contenteditable=True>
[..]
答案 1 :(得分:0)
我所知道的没有内置的短路方式。您提出问题的方式,它将搜索整个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);
答案 2 :(得分:0)
您可以使用以下事实:在连接中保留第一个集合的排序顺序。因此,请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();