2014-02-21 9 views
1

나는 추상 클래스 Athlete의 배열을 가지고있다.특정 하위 유형이있는 배열에서 가장 높은 값, 두 번째로 높은 값, 세 번째로 높은 값을 결정합니까?

{ 
     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"); 

    } 

Athlete 클래스에는 averageScore라는 필드가 있습니다. 나는 각기 다른 어린이 유형에 따라 선수를 기반으로 한 아동 수업을 가지고 있습니다. 배열에서 각 자식 유형의 상위 3 개 평균 점수를 찾을 수 있기를 원합니다. 더 많은 운동 선수가 추가되면 나는 여전히 최고 3 명만 찾을 수 있기를 원합니다. 어떻게 할 것입니까? 미안하지만 프로그래밍에 익숙하지 않고 전에는 어린이 유형을 사용한 적이 없습니다. 나는 어디에서 시작해야할지 모른다.

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

.. 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 개 평균 점수를 찾을 수 있기를 원합니다. 정렬." –

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

배열과 비슷한 기능을 수행 할 수 있습니다. 대신 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,과 같이 : d2894 @

foreach (var skier in top3Skiers) 
    Console.WriteLine("{0} - {1}", skier.Name, skier.AverageScore); 
관련 문제