Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于阵列的LINQ+短路_C#_Arrays_Linq - Fatal编程技术网

C# 基于阵列的LINQ+短路

C# 基于阵列的LINQ+短路,c#,arrays,linq,C#,Arrays,Linq,我有一个简单的LINQ查询,我想基于数组中的第一个匹配值对其进行短路。我只想返回,基于xmlDoc中匹配数组中第一项的第一个值,例如,如果它匹配B,那么它将退出,如果它不匹配,那么它将尝试匹配C等等 我当然可以手动遍历数组并验证值是否为NULL,这可能是我必须要做的,但我一直在寻找是否有更优雅的方法来实现这一点 非常感谢, 瑜伽士 }否,但可以将循环设置为xDoc.genderantsRoot的单个循环,该循环由linq在内部循环,并减少对数组的查找 首先从searchTypes创建查找字典:

我有一个简单的LINQ查询,我想基于数组中的第一个匹配值对其进行短路。我只想返回,基于xmlDoc中匹配数组中第一项的第一个值,例如,如果它匹配B,那么它将退出,如果它不匹配,那么它将尝试匹配C等等

我当然可以手动遍历数组并验证值是否为NULL,这可能是我必须要做的,但我一直在寻找是否有更优雅的方法来实现这一点

非常感谢,

瑜伽士


}

否,但可以将循环设置为xDoc.genderantsRoot的单个循环,该循环由linq在内部循环,并减少对数组的查找

首先从searchTypes创建查找字典:

现在对于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方法,但您可以构建自己的自定义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;
}

您可以使用这样一个事实:在联接中,第一个集合的排序顺序是保留的。因此,将serachTypes与xDoc.genderantsRoot连接起来,并获取第一个元素:

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();

如果您提供一个简短但完整的示例,并提供示例输入和预期输出,那么帮助您会容易得多。我不明白你现在想做什么。如果你说的优雅是指一个Linq查询,无论谁读到它都能清楚它在做什么,那么不,没有一个优雅的解决方案。坚持使用一个你能理解并能解释的循环。比如searchTypes.Containsr.ElementdCode.Value.ToString?@ArthurRey,这会以错误的方式短路。谢谢各位,谢谢你们的回复。好的,我更新了代码,展示了我在forLoop中的做法。感谢这与Jon下面的答案几乎相同,但返回实际节点而不是值,它不使用字典,并封装到扩展方法中。他的答案实际上更好,所以我会对他的答案投赞成票。我将把这个留作例子,但你应该用他的答案。我相信在大多数情况下,他使用字典的伸缩性比使用数组要好
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;
}
string[] searchTypes = { "B", "C", "D", "A" };
XDocument xDoc = XDocument.Parse(xmlString);
var bestNode=xDoc.Descendants("Root")
  .Where(r=>r.Element("dCode")!=null)
  .FindBestNode(searchTypes);
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();