基于数组

时间:2015-10-08 16:46:43

标签: c# arrays linq

我有一个简单的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;
                }

}

3 个答案:

答案 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"1int 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();