views:

93

answers:

3

LINQ2Xml: I would like to get the count of elements where candidate has won in every province. I need some help.

<Pronvice_Data>
    <Pronvice>PronviceA</Pronvice>
    <Registered_Voters>115852</Registered_Voters>
    <Sam_Kea>100</Sam_Kea>
    <Jeje>500</Jeje>
    <John_Doe>400</John_Doe>
</Pronvice_Data>

<Pronvice_Data>
    <Pronvice>PronviceA</Pronvice>
    <Registered_Voters>25852</Registered_Voters>
    <Sam_Kea>200</Sam_Kea>
    <Jeje>100</Jeje>
    <John_Doe>300</John_Doe>
</Pronvice_Data>

<Pronvice_Data>
    <Pronvice>PronviceC</Pronvice>
    <Registered_Voters>317684</Registered_Voters>
    <Sam_Kea>1000</Sam_Kea>
    <Jeje>1200</Jeje>
    <John_Doe>190</John_Doe>
</Pronvice_Data>

Expected Result:

Candidate | Won In
Jeje         2
John_Doe     1
Sam_Kea      0   
+3  A: 

OK, I didn't like the data format, so I changed it to this:

<root>
  <Candidates>
    <Sam_Kea/>
    <Jeje/>
    <John_Doe/>
  </Candidates>

  <Provinces>
    <Province name='ProvinceA' Registered_Voters='115852'>
      <Candidate name='Sam_Kea' votes='100'/>
      <Candidate name='Jeje' votes='500'/>
      <Candidate name='John_Doe' votes='400'/>
    </Province>

    <Province name='ProvinceB' Registered_Voters='25852'>
      <Candidate name='Sam_Kea' votes='200'/>
      <Candidate name='Jeje' votes='100'/>
      <Candidate name='John_Doe' votes='300'/>
    </Province>

    <Province name='ProvinceC' Registered_Voters='317684'>
      <Candidate name='Sam_Kea' votes='1000'/>
      <Candidate name='Jeje' votes='1200'/>
      <Candidate name='John_Doe' votes='190'/>
    </Province>
  </Provinces>

</root>

And this is the LINQ-to-XML code I used:

public void Run()
{
    string fileToLoad = this.GetType().Name + ".xml";

    XElement root = XElement.Load(fileToLoad);

    // =======================================================
    System.Console.WriteLine("\nCandidates:");
    var allCandidates = from c in root.Element("Candidates").Elements()
        select c.Name;

    foreach (var d in allCandidates)
        Console.WriteLine("  {0}", d.ToString());


    // =======================================================
    System.Console.WriteLine("\nNumber of Candidates in each Province:");

    var s1 = from p in root.Element("Provinces").Elements()
        select new
            {
                Prov = (string) p.Attribute("name"),
                NumCandidates = p.Elements("Candidate").Count()
            };

    foreach (var d in s1)
        Console.WriteLine("  {0}", d.ToString());


    // =======================================================
    System.Console.WriteLine("\nCandidate with most votes:");
    var s2 = from p in root.Element("Provinces").Elements()
        let maxVotes = (from c in p.Elements("Candidate") select c)
                       .Max(x => ((int)x.Attribute("votes")))

        select new
            {
                Prov = (string) p.Attribute("name"),
                Voters = (int) p.Attribute("Registered_Voters"),
                Candidate = (from c in p.Elements("Candidate")
                             select c).Where(x => ((int)x.Attribute("votes")) == maxVotes)
                    .First().Attribute("name").Value
            };

    foreach (var d in s2)
        Console.WriteLine("  {0}", d.ToString());


    // =======================================================
    System.Console.WriteLine("\nCandidates and the # of provinces won:");

    var s4 = from can in allCandidates
        let count = (from p in s2 where p.Candidate == can select p).Count()
        orderby count descending
        select new { Candidate = can, NumberOfProvincesWon = count };

    foreach (var d in s4)
        Console.WriteLine("  {0}", d.ToString());
}

Output:

Candidates:
  Sam_Kea
  Jeje
  John_Doe

Number of Candidates in each Province:
  { Prov = ProvinceA, NumCandidates = 3 }
  { Prov = ProvinceB, NumCandidates = 3 }
  { Prov = ProvinceC, NumCandidates = 3 }

Candidate with most votes:
  { Prov = ProvinceA, Voters = 115852, Candidate = Jeje }
  { Prov = ProvinceB, Voters = 25852, Candidate = John_Doe }
  { Prov = ProvinceC, Voters = 317684, Candidate = Jeje }

Candidates and the # of provinces won:
  { Candidate = Jeje, NumberOfProvincesWon = 2 }
  { Candidate = John_Doe, NumberOfProvincesWon = 1 }
  { Candidate = Sam_Kea, NumberOfProvincesWon = 0 }
Cheeso
Thanks so much this will help me. Your format is good but that means that i have to recreate this.
The challenge with the XML structure in your question is, how can a program tell the difference between a candidate name, and another XML element? For example `Registered_Voters` is an element in your document, and its text value is an integer. The same is true for `Sam_Kea`. Only one of them is a Candidate. Which one? The structure of the XML in your question seems a little "loose".
Cheeso
Thanks so much Cheeso. I got it to work for me.They are hardcore linq expressions though! How do you easily get them to work.Now, i need to get the percentages by which each candidate won.
Hi,How can i get the percentage to work. My Actual percentage should be (Total_Vote_Cast_For_Candidate_in_all_Provinces/Total_Votes_Cast_In All_Pronvinces) * 100
That's a new question!
Cheeso
Yes, its a new question, but part of the orignal. I am just failing with the Sums. Help.
I wanted it to be part of var s4 like below, From my Calculation { Candidate = Jeje, NumberOfProvincesWon = 2,PercentageVotes = 32.06%}{ Candidate = John_Doe, NumberOfProvincesWon = 1 ,PercentageVotes= 17.84%}{ Candidate = Sam_Kea, NumberOfProvincesWon = 0 ,PercentageVotes=26.05%}BTW, in the var s2, you confused the Registered_Voters to be the total Votes cast for the Candidate. These are bound to the province alone
I can't figure this out: Please Help.Percentage for Sam_Kea=(Total_Sum_Of_Votes_Cast_for_Sam_Kea_In_All_Pronvinces / Total_Sum_Of_Votes_Cast_For_All_Candidates_In_All_Pronvinces)* 100.
Got it to work.
A: 

Arrgh. Failed Failed Failed...

ok lets start from here. I have this below but it just gives me the votes of the candidate in each district.

var sumVotes= from sm in root.Elements()
            group sm by new { groupedData= sm.Elements("Provinces")} into g
        select new { Sam_Kea=g.Sum(el=>(int)el.Element("Candidate").Attribute("Votes"))
                  };
A: 

Its hard for me to deal with Attribute Values. From the orignal format, i would get it using the code below.

var Percentages= from elem in xmlVectors2.Descendants("Province_Data")
          where elem.Elements().Count() > 1
          group elem by new { groupedData = elem.Element("Province_Data")} into g
          let votesSam_Kea=g.Sum(elem =>(int)elem.Element("Sam_Kea"))
          let votesJeje=g.Sum(elem =>(int)elem.Element("Jeje"))
          let votesJohn_Doe= g.Sum(elem =>(int)elem.Element("John_Doe"))              
          let totVotesCast=votesSam_Kea+ votesJeje+ votesJohn_Doe
          select new {
             Percent_Sam_Kea= Math.Round((double)(votesSam_Kea*100)/totVotesCast,2),
             Percent_Jeje=Math.Round((double)(votesJeje*100)/totVotesCast,2),
             Percent_John_Doe=Math.Round((double)(votesJohn_Doe*100)/totVotesCast,2),                
             VotesCast= totVotesCast,
             RegisteredVoters = g.Sum(elem => (int)elem.Element("Registered_Voters"))
             };
Never Mind, i got it to work