2014-02-21 22 views
1

我有一個抽象類運動員的數組。確定具有特定子類型的數組中的最高,次高,第三高值?

{ 
     athletes[0] = new BobSledder("Bobby", "Ben and Bill"); 
     athletes[1] = new BobSledder("Burt", "Bonnie and Baek"); 
     athletes[2] = new BobSledder("Barnie", "Blues and Bart"); 
     athletes[3] = new Skier("Sally", "downhill"); 
     athletes[4] = new Skier("Sarah", "downhill"); 
     athletes[5] = new Skier("Sam", "downhill"); 
     athletes[6] = new IceSkater("Suzy", "blue"); 
     athletes[7] = new IceSkater("Sullie", "red"); 
     athletes[8] = new IceSkater("Sierra", "orange"); 

    } 

有一個在運動員類稱爲averageScore場。我爲每種不同的孩子類型都有基於Athlete的兒童班。我希望能夠找到數組中每個子類型的前3個averageScores。如果增加更多運動員,我希望能夠只找到前三名。我該怎麼做呢?我很抱歉,我對編程相當陌生,以前從未使用過類型的孩子。我不知道從哪裏開始。

public abstract class Athlete 
{ 
    string name; 
    int eventsRun; 
    int lastScore; 
    int runningTotal; 
    double averageScore; 

    public Athlete() 
    { 
    } 

    public Athlete(string name) 
    { 
     this.name = name; 
    } 

    public string Name { get { return name; } } 
    public int EventsRun { get { return eventsRun; } } 
    public int LastScore 
    { 
     get { return lastScore; } 
     set 
     { 
      lastScore = value; 
      eventsRun++; 
      runningTotal += lastScore; 
      averageScore = runningTotal/eventsRun; 
     } 
    } 
    public double AverageScore { get { return averageScore; } } 
+0

@ d2894 ..什麼是averageScore ..這 –

+0

建議爲今後的節目的代碼片段:不重複的標籤標題。有關信息,請參閱http://stackoverflow.com/help/tagging。 :) – Crono

+0

@RevanayyaHiremath新增 – d2894

回答

2

在.NET 3.5或以上:

var topThreePerSubtype = athletes.GroupBy(x => x.GetType()).Select(g => g.OrderByDescending(x => x.averageScores).Take(3)); 

這實際上將返回的IEnumerable<Athlete>IEnumerable,這可能不是最好的。我建議你使用TopThree類或類似的屬性來表示結果實例。

下面是一個(簡單化)例如:

public class TopThree 
{ 
    public Type SubType {get; set;} 
    public IEnumerable<Athlete> Athletes {get; set;} 
} 

(...) 

var topThreePerSubtype = athletes.GroupBy(x => x.GetType()).Select(g => new TopThree() { SubType = g.Key, Athletes = g.OrderByDescending(x => x.AverageScores).Take(3)}); 

什麼是偉大的這個做法是,即使你添加一個全新的學科,將能爲您創建另一個前三名對象。不需要額外的代碼。

當然,因爲這使得使用LINQ擴展你必須確保你有這樣對你的文件的頂部:

using System.Linq; 
+0

只打了幾秒 – user1477388

+0

@ user1477388你可以在3.5之前回答如何做,這仍然是有用的信息。 (我懶得自己做:)) – Crono

+1

這並不完全回答OP要找的內容,它是:「我希望能夠找到每個孩子類型的前3個averageScores在陣「。 –

0

首先,我會用運動員的名單,而不是一個數組,因爲你想成爲能夠改變運動員和陣列的數量應該只在內部數字不會改變時才能使用。

,那麼你必須:

List<Athlete> athletes = new List<Athlete>{/*Whatever athlete's you're adding at the start*/}; 

List<Athlete> athletes = new List<Athlete>(); 
athletes.Add(new BobSledder("Bobby", "Ben and Bill")); 
... 

這允許你改變運動員的數量在運行時更容易一些。通過他們的運動將每個運動員分開也可能更容易,而不是將它們全部保存在單個列表/陣列中,因爲它最終可能更乾淨或更簡單,但我不確定你的最終目標是什麼所以我不能肯定地說哪種方法更好。如果這不是你需要根據單獨的運動處理運動員的唯一場所,那麼你可能想要考慮將它們分成單獨的列表,每個運動項目一個。至少要記住一些事情。

然後,你可以簡單地使用在運動員foreach循環,並用類似發現前3:

double minScore = 0; 
double maxScore = 0; 
double midScore = 0; 

foreach(Athlete player in Athletes){ 
    if (player.averageScore >= minScore) { 
     minScore = midScore; 
     midScore = maxScore; 
     maxScore = player.averageScore; 
    } else if (player.averageScore >= midScore) 
     minScore = midScore; 
     midScore = player.averageScore; 
    } else if (player.averageScore >= minScore); 
     minScore = player.averageScore; 
    } 
} 

雖然上面的代碼只能找到前3分掉所有的運動員,你可以設置一組唯一您的每一個運動,然後分數像

if(player.GetType() == typeof(Skier)) 

篩選出來用什麼來確定哪些設置要切換到。我仍然建議如果你經常需要在運動方面與他們打交道,那麼運動員就可以通過運動來分流運動員,因爲這樣會讓一切都變得簡單。

如果其拆分成單獨的列表,你可以作出這樣一個功能:

private double[] getTopThreeScores(List<Athlete> inAthletes){ 
    //Use this instead of the min/max/mid and then access by the index 
    double[3] topScores = new double{0.0,0.0,0.0}; 

    /*Loop from above, but switch out topScores[0] for minScore, topScores[1] for mid, etc.*/ 

    return topScores; 
} 

希望這有助於一點。

保持陣列:

private double[] getTopThreeScores(object inSport, Athlete[] inAthletes){ 
    Type sportType = inSport.GetType(); 
    double[3] topScores = new double{0.0,0.0,0.0}; 
    int length = inAthletes.Length; 
    for(int i = 0; i < length; i++){ 
     if(inAthletes[i].GetType() == sportType){ 
      if (player.averageScore >= minScore) { 
       minScore = midScore; 
       midScore = maxScore; 
       maxScore = player.averageScore; 
      } else if (player.averageScore >= midScore) 
       minScore = midScore; 
       midScore = player.averageScore; 
      } else if (player.averageScore >= minScore); 
       minScore = player.averageScore; 
      } 
     } 
    } 
    return topScores; 
} 

將被稱爲像

getTopThreeScores(new Skier(), athletes); 

,或者你可以在一個特定的運動員通過。

不一定是最乾淨的方式,但它會工作,並允許您指定不同的類型。我沒有編譯這個,所以可能會有一些小錯誤。

+0

你可以做一些與數組類似的事情,只需使用標準for循環而不是foreach即可。如果您需要添加內容,只需使用列表更簡單。如果您必須保持陣列不變,只需使用類型檢查來確定您需要更改哪組分數,然後僅更改這些分數。您也可以將分數添加到每項運動的列表中,然後對其進行排序,並將排名前3。 – jhyatt

0

你提到:

我希望能夠找到陣列中的每個子類型的前3 averageScores。

所以,我提出以下解決方案:

var top3Skiers = athletes.OfType<Skier>() 
    .OrderByDescending(s => s.AverageScore).Take(3); 

與其他解決方案,這需要使用System.Linq命名空間的工作。 OfType將僅選擇指定類型的對象,允許您過濾出您想要的內容。這意味着如果您想選擇排名前3 IceSkater,您可以指定OfType<IceSkater>()

爲了列舉的結果,您可以foreach他們,就像這樣:

foreach (var skier in top3Skiers) 
    Console.WriteLine("{0} - {1}", skier.Name, skier.AverageScore); 
相關問題