Как у вас 2 предложения where в инструкции linq xml - PullRequest
1 голос
/ 07 декабря 2010

У меня есть следующий XML, и мне нужен запрос, который будет извлекать Year и Return_Value при прохождении определенной статистики.

Текущий код не работает, потому что вы не можете иметь два предложения where в одном операторе add для объекта словаря.Есть ли этому решение?

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"

Редактировать

В следующем утверждении - в идеале я бы хотел, чтобы дважды дважды отфильтроватьэто не 1 процентиль.

 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 Ответ

2 голосов
/ 07 декабря 2010

Я действительно очень смущен вашим запросом 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. имеют 2 предложения where в инструкции linq xml
  2. имеет два предложения where в одном операторе add для объекта словаря
  3. ВЫБРАТЬ * ИЗ МОИХ ДАННЫХ
  4. отфильтровывают те, которые не являются 1-процентным

Я проигнорирую первые два, потому что я не думаю, что они необходимы. Третье требование относительно простое, если предположить, что ваш формат данных несколько фиксирован. (Вы действительно хотели иметь один тег "Year" и один тег "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

ГДЕ только статистика = "0 процентиль, 25 процентиль, 50 процентиль, 75 процентиль "и т. д.

Итак, когда вы говорили о пунктах 2 where, вы подразумевали, что вы хотите, например, "где процентиль = 0 или процентиль = 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...