【问题标题】:Optimisation of LinqToXmlLinq To xml的优化
【发布时间】:2016-10-07 21:22:25
【问题描述】:

谁能告诉我这是否正确,或者是否有更快/更清洁的方法?

//I load p as a xDoc so I can use linq to xml
    XDocument myDoc = XDocument.Parse(p);
    // retrieve each "Item" node except if orderedQuantity is 0 or name is "nullorderitem"
    IEnumerable<XElement> orderedRes = from item in myDoc.Descendants("Item")
                                       where ((double)item.Element("orderedQuantity") > 0 &&     item.Element("ResourceId").Name != "NULLOrderItem")
                                       select item;

    foreach (XElement xelem in orderedRes)
    {
        if(xelem.Element("Name").Value.ToLower() == "oneofmyvalueIneed" 
            || xelem.Element("Name").Value.ToLower() == "anotherone"
            || xelem.Element("Name").Value.ToLower() == "yetanother")
        {
            FieldProperties elem = new FieldProperties();
            elem.Fieldname = xelem.Element("Name").Value;
            elem.Fieldvalue = xelem.Element("OrderedQuantity").Value;
            lElem.Add(elem);
        }
    }

知道 lElem 是一个 FieldProperties 的列表,而 FieldProperties 是一个看起来像这样的类:

FieldProperties
string fieldname
string fieldvalue 

而 p 是一个字符串,看起来像

<items>
<item>
 <resourceid>blablabla</resourceid>
 <somerandomtag>whocares</somerandomtag>
 <orderedquantity>0.0</orderedquantity>
</item>
<item>
 <resourceid>oneofmyvalueIneed</resourceid>
 <somerandomtag>whocares</somerandomtag>
 <orderedquantity>1.0</orderedquantity>
</item>
<item>
 <resourceid>yetanother</resourceid>
 <somerandomtag>whocares</somerandomtag>
 <orderedquantity>0.0</orderedquantity>
</item>
</items>

【问题讨论】:

  • 这部分没有意义:item.Element("ResourceId").Name != "NULLOrderItem")。名称始终为ResourceId,它将始终返回true。你的意思是Value
  • 这可能属于code review。这并没有什么问题(除了我指出的错误)。我可能会将 XML 投影到您的对象 首先,然后过滤(因为过滤会更容易一些)。
  • Charles Mager ==> 关于价值完全正确。愚蠢的错误。另外,很抱歉将其发布在错误的部分,甚至不知道有代码审查部分,仍然是新用户。但是我不明白“先投影你的xml然后过滤”的意思,这不是我做的吗? €dit = 好的,看到下面的答案我现在明白了。

标签: c# xml linq


【解决方案1】:

您可以使用.Contains 方法改进if 语句。

var validNames = new List<string> {"oneofmyvalueIneed","anotherone","yetanother"}

XDocument myDoc = XDocument.Parse(p);
var result = from item in myDoc.Descendants("Item")
      where ((double)item.Element("orderedQuantity") > 0 &&                   
            item.Element("ResourceId").Name != "NULLOrderItem") && // See Charles's comment about this line
            validNames.Contains(iten.Element("Name").Value.ToLower())
      select item;

foreach (var item in orderedRes)
{
    FieldProperties elem = new FieldProperties();
    elem.Fieldname = xelem.Element("Name").Value;
    elem.Fieldvalue = xelem.Element("OrderedQuantity").Value;
    lElem.Add(elem);
}

那么你也可以将foreach替换为

select new FieldProperties
{
    Fieldname = item.Element("Name").Value,
    Fieldvalue = xelem.Element("OrderedQuantity").Value
};

在访问子元素时将它们加在一起+一些优化:

var validNames = new List<string> {"oneofmyvalueIneed","anotherone","yetanother"}

XDocument myDoc = XDocument.Parse(p);
var result = from item in myDoc.Descendants("Item")
      let value = item.Element("orderedQuantity")
      let name = iten.Element("Name").Value.ToLower()
      where ((double)value > 0 &&                   
            item.Element("ResourceId").Name != "NULLOrderItem") && // See Charles's comment about this line
            validNames.Contains(name)
      select new FieldProperties
      {
          Fieldname = name
          Fieldvalue = value
      };

【讨论】:

  • @CharlesMager - ops true :) 愚蠢的错误。更正
  • 谢谢!为了使您的答案对下一位观众有效,您可能需要编辑 foreach 子句: item ==> xelem (或在循环中将 xelem 替换为项目)完美的答案,10/10 谢谢 :)
  • 我赞成你的回答,但我可以自己去他妈的,因为我没有足够的代表:(
  • 但是在上一个版本中,字段属性是如何添加到列表中的?你创建了一个新的 fieldproperties,但你没有用它做任何事情?
  • @DoctorPrisme - 如果您创建此列表并仅使用此 linq 中的项目填充它,则只需将 result 替换为该列表并在选择末尾添加 ToList()。如果您有一个列表并想添加这些项目,请使用:lElem,AddRange(result);
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多