Xdocument - 删除除最后一个c#之外的重复元素

时间:2015-11-13 12:37:40

标签: c# linq linq-to-xml

我想从MatchOdds节点中删除所有重复的Bet元素,但下一个xml示例中的最后一个元素除外,而不是将文件保存在另一个目标中。

<Sports>
  <Sport id="5" name="Tennis">
    <Tournament id="3" name="ATP - Basel, Switzerland">
      <Match id="8331188" name="Nadal, Rafael v Gasquet, Richard" 
          startDate="2015-10-31T13:30:00">
        <MatchOdds>
          <Bet id="20">
            <Outcome Special="" name="1" odds="1.35" />
            <Outcome Special="" name="2" odds="3.3" />
          </Bet>
          <Bet id="204">
            <Outcome Special="" name="1" odds="1.45" />
            <Outcome Special="" name="2" odds="2.85" />
          </Bet>
          <Bet id="231">
            <Outcome Special="" name="1" odds="1.45" />
            <Outcome Special="" name="2" odds="2.75" />
          </Bet>
          <Bet id="206">
            <Outcome Special="" name="2 sets" odds="1.55" />
            <Outcome Special="" name="3 sets" odds="2.35" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="12312333322" />
            <Outcome Special="" name="2:1" odds="123123" />
            <Outcome Special="" name="0:2" odds="123123123" />
            <Outcome Special="" name="1:2" odds="123123123" />
          </Bet>
        </MatchOdds>
      </Match>
    </Tournament>
  </Sport>
</Sports>

我想使用LINQ - to - XMl(Xdocument类)来做,但我不知道如何。 你能帮我解决这个问题吗? 提前致谢

2 个答案:

答案 0 :(得分:2)

您可以尝试按ID分组,稍后如果某个组有多个元素删除第一个count-1元素:

   var query = from el in doc.Descendants("Bet")
               group el by el.Attribute("id").Value;

   foreach (var g in query)
   {
      int count=g.Count();
      if (count>1)
      {
         g.Take(count - 1).Remove();// remove every node in the source collection from its parent node
      }
   }

答案 1 :(得分:1)

不清楚你的意思是相同的......在没有更好的相同定义的情况下,我会在这里假设所有的赌注元素是相同的。

假设您使用的是上面引用的非破坏版XML:

var bets = doc.Root.Descendants("MatchOdds").Descendants("Bet").ToList();
var lastBet = bets.Last();

foreach(var bet in bets)
{
    if(bet != lastBet)
    {
        bet.Remove();
    }
}

现在是一个更明智的定义&#34;相同&#34;可能是那些共享相同id

的人

我选择在这里使用a WithoutLast extension method我随手可得:

static class Ex
{
    public static IEnumerable<T> WithoutLast<T>(this IEnumerable<T> source)
    {
        using (var e = source.GetEnumerator())
        {
            if (e.MoveNext())
            {
                for (var value = e.Current; e.MoveNext(); value = e.Current)
                {
                    yield return value;
                }
            }
        }
    }
}

那么你可以拥有这个可爱的LINQy解决方案来解决这个问题:

var bets = doc.Root.Descendants("MatchOdds").Descendants("Bet");
var betsToRemove = bets.GroupBy(b => (string)b.Attribute("id"))
                       .SelectMany(g => g.WithoutLast())
                       .ToList();
betsToRemove.ForEach(b => b.Remove());