你如何在linq xml语句中有2个where子句

时间:2010-12-07 17:06:13

标签: xml linq silverlight dictionary

我有以下XML,我需要一个查询,当您通过特定统计信息时,它将提取Year和Return_Value。

当前代码不起作用,因为在一个字典对象的add语句中不能有两个where子句。这个问题有方法解决吗?

foreach (var row in rows)
{
    myHoldingsDistribution.Add(row.Descendants()
        .Where(y => y.Name.LocalName == keyName)
        .Select(q => q.Value).Max(), 
        Double.Parse(row.Descendants().Where(y => y.Name.LocalName == valueName)
                           .Select(q => q.Value).Max()) * multiplier);

<Table>
  <Year>1</Year>
  <Statistic>0 Percentile</Statistic>
  <Return_Value>0.0535644000000</Return_Value>
</Table>
    base {System.Xml.Linq.XContainer}: <Table>
  <ALMRunResults_Year>1</ALMRunResults_Year>
  <Statistic>0 Percentile</Statistic>
  <Return_Value>0.0535644000000</Return_Value>
</Table>

    FirstAttribute: null
    HasAttributes: false
    HasElements: true
    IsEmpty: false
    LastAttribute: null
    Name: {Table}
    NodeType: Element
    Value: "10 Percentile0.0535644000000"

修改

在下面的陈述中 - 我理想地希望.where两次来过滤那些不是1 Percentile的那些。

 myHoldingsDistribution.Add(row.Descendants() 
        .Where(y => y.Name.LocalName == keyName) 
        .Select(q => q.Value).Max(),  
        Double.Parse(row.Descendants().Where(y => y.Name.LocalName == valueName) 
                           .Select(q => q.Value).Max()) * multiplier); 

1 个答案:

答案 0 :(得分:2)

我对你的LINQ查询非常困惑,看起来你在第一段中描述的行为并没有真正反映你的代码试图做的事情。我相信你对代码的问题更多地与你的Double.Parse方法的位置有关,因为下面的代码编译并运行得很好:

var myHoldingsDistribution = new Dictionary<object, object>();
var rows = new[] {new {Descendants = new[]{new {Name = new {LocalName = "test"}, Value = 0.05}}}};
var keyName = "test";
var valueName = "test";
var multiplier = 2d;
foreach (var row in rows)
{
    myHoldingsDistribution.Add(row.Descendants
        .Where(y => y.Name.LocalName == keyName)
        .Select(q => q.Value).Max(), 
        row.Descendants.Where(y => y.Name.LocalName == valueName)
                        .Select(q => q.Value).Max() * multiplier);

}

修改

这个问题我仍然很困惑。到目前为止,您已经满足了以下要求:

  1. 在linq xml语句中有2个where子句
  2. 在一个字典对象的add语句中有两个where子句
  3. SELECT * FROM my dataset
  4. 过滤掉不是1 Percentile
  5. 的那些

    我会忽略前两个因为我不认为它们是必要的。假设您的数据格式有些固定,第三个要求相对简单。 (你真的想要一个“年”标签和一个“ALMRunResults_Year”标签吗?)

    // Move the data into an object that can easily be manipulated.
    var transform = from r in rows
                    select new 
                    {
                        key = r.Element(keyName).Value,
                        value = Double.Parse(r.Element(valueName).Value),
                        statistic = r.Element(statisticName).Value
                    };
    

    一旦你选择了这样的值,就可以使用LINQ to Objects来执行你描述的过滤器,并通过调用ToDictionary从结果集合中创建一个字典:

    var myHoldingsDistribution = transform
        // Filter out anybody that's not 1 percentile
        .Where(r => r.statistic == statisticFilter)
        // Create a dictionary out of the keys and values
        .ToDictionary(r => r.key, r => r.value);
    

    我给你编译并运行的两个代码块给出了以下设置:

    var text = 
    @"<Root>
        <Table>
            <ALMRunResults_Year>1</ALMRunResults_Year>
            <Statistic>0 Percentile</Statistic>
            <Return_Value>0.0535644000000</Return_Value>
        </Table>
        <Table>
            <ALMRunResults_Year>2</ALMRunResults_Year>
            <Statistic>1 Percentile</Statistic>
            <Return_Value>0.0535644000000</Return_Value>
        </Table>
    </Root>";
    var doc = XDocument.Parse(text);
    var rows = doc.Descendants("Table");
    
    var keyName = "ALMRunResults_Year";
    var valueName = "Return_Value";
    var statisticName = "Statistic";
    var statisticFilter = "1 Percentile";
    

    这有意义吗?

    修改2

      

    WHERE统计仅=“0百分位,   25百分位,50百分位数,75   百分位“等等

    所以当你在谈论2个where子句时,你的意思是你想要“where percentile = 0或percentile = 25”,例如?有几种方法可以做到这一点。最简单的可能是使用Contains方法:

    var statisticFilters = new[]{
        "0 Percentile", "25 Percentile", "50 Percentile", "75 Percentile"
    };
    ...
    var myHoldingsDistribution = transform
        .Where(r => statisticFilters.Contains(r.statistic))
        .ToDictionary(r => r.key, r => r.value);