2016-09-24 5 views
0

시뮬레이션 결과라는 개체가 있습니다.linq을 사용하는 카운트 그룹

public SimulationResult 
{ 
     public Horse Winner {get;set;} 
     public Horse Second {get;set;} 
     public Horse Third {get;set;} 
     public Horse Fourth {get;set;} 
    } 

    public Horse 
    { 
     public Guid Id{get;set;} 
    } 

그래서 50000 SimulationResult의 목록이 있습니다. 가장 일반적인 50 가지 결과를 어떻게 결정할 수 있습니까?

LINQ groupBy를 사용했지만 각 개체에 horseId가 표시되고 하나의 값이 여러 번 나타날 수 없습니다.

EDIT 죄송합니다. 분명히 알았습니다. 그래서 총 8 마리의 말이 있습니다. 말은 1 ~ 8입니다.

그래서 시뮬레이션 결과 1 승자가, 제 2, 제 3 1, 2, 3, 네 번째 두 번째 세 번째는, 제 2 5의 시뮬레이션 결과에서 4

제 7 6이다 8이다. 시뮬레이션 결과에서 제 3

는 제 1, 2, 제 3, 제 그래서 1 결과 세트 3이 동일한 결과 집합 4

이다. 따라서이 샘플에서 우승자 1 초 2 3 3 4 4가 가장 일반적인 결과입니다. 귀하의 질문에

+2

"가장 일반적인"이라고 정의해야 할 필요가 있습니까? – TigOldBitties

+0

당신은 테이블 구조를 공유하고 정확히 무엇을 원하는지 예제를 제공해 주실 수 있습니까 –

+0

질문을 편집했습니다. 잘하면 그게 더 명확하게. – DidIReallyWriteThat

답변

1

간단한 대답은 :

class ExactResult { 
    public String CombinedId { get; set; } 
    public int Count { get; set; } 
} 
resultList.Select(l => { 
    var combinedId = l.Winner.Id.ToString() + l.Second.Id.ToString() + l.Third.ToString() + l.Fourth.ToString(); 
    return new ExactResult() { CombinedId = combinedId), Count = l.Count(c => c.Winner.Id.ToString() + c.Second.Id.ToString() + c.Third.ToString() + c.Fourth.ToString();)} 
}).OrderByDescending(e => e.Count).Take(50) 

대답은하지만 의미가 없다. 당신이 실제로하려고하는 것이 많은 결과에서 가장 가능성이 큰 4 명의 승자라면, 이것은 그것에 대해가는 길이 아닙니다. 이것은 정확히 같은 4 명의 승자와 함께 가장 많은 결과를 보여줄 것입니다. 아마도 당신이 찾고있는 것은 통계 분석이거나 확산 될 수 있습니다. 어쨌든 당신이 실제로 묻는 것보다 더 복잡한 것.

+0

나는 (저조한) 내가 묘사 한 것을 찾고있다. 가장 일반적인 4 명의 승자를 얻는 방법을 알아 냈지만 정확한 순서로 상위 4 위가 가장 필요합니다. – DidIReallyWriteThat

1

은 어쩌면이 당신을 위해 무엇을 찾고있는 사람입니다 :

var q = (from x in mySimulationResultList 
     group x by x into g 
     let count = g.Count() 
     orderby count descending 
     select new { Value = g.Key, Count = count }).Take(50); 

foreach (var x in q) 
{ 
    Console.WriteLine($"Value: {x.Value.ToString()} Count: {x.Count}"); 
} 

하는 당신을위한 의미있는 출력을 원하는 경우 Console.WriteLine 당신이 EqualsGetHashCode를 오버라이드 (override) 할 필요가 당신은 HorseSimulationResult

에 대한 ToString를 오버라이드 (override) 할 필요가 , 다음과 같은 내용 :

public override bool Equals(object obj) 
{ 
    SimulationResult simResult = obj as SimulationResult; 
    if (simResult != null) 
    { 
     if (Winner == simResult.Winner 
      && Second == simResult.Second 
      && Third == simResult.Third 
      && Fourth == simResult.Fourth) 
     { 
      return true; 
     } 
    } 
    return false; 
} 
public override int GetHashCode() 
{ 
    int hash = 12; 
    hash = hash * 5 + Winner.GetHashCode(); 
    hash = hash * 5 + Second.GetHashCode(); 
    hash = hash * 5 + Third.GetHashCode(); 
    hash = hash * 5 + Fourth.GetHashCode(); 
    return hash; 
} 

소스 here (요청에 의한 그룹)와 here (서로에 대한 비교 객체)

3

내가 LINQ GROUPBY를 사용하여 시도하지만 horseId 각 개체에 표시하고 하나 개의 값을 여러 번 허용하지 않습니다.

당신은 명시 적으로 지정하는 대부분의 시간을 우리는 우리가 항상 할 수있는 (그리고 여기가 필요의), 컴파일러는 우리의 이름을 추측 할 수 있지만, Grouping by Composite Keys에 설명 된대로 익명 형식을 사용하여 의미하는 경우 :

var topResults = simulationResults 
    .GroupBy(r => new 
    { 
     WinnerId = r.Winner.Id, 
     SecondId = r.Second.Id, 
     ThirdId = r.Third.Id, 
     FourthId = r.Fourth.Id, 
    }) 
    .OrderByDescending(g => g.Count()) 
    .Select(g => g.First()) // or new { Result = g.First(), Count = g.Count() } if you need the count 
    .Take(50) 
    .ToList(); 
+0

이것은 아름답고 완벽합니다. 이 문제를 어떻게 생각해 냈는지, 아니면 많은 LINQ 연습을했는지에 대한 정보가 있습니까? – DidIReallyWriteThat

+1

하나의 소스는 물론 대답의 링크이며, 다른 하나는 [익명 형식 (C# 프로그래밍 가이드)] (https://msdn.microsoft.com/en-us/library/bb397696.aspx)입니다. 많은 실험과 SO 퍼즐과 함께 오는 경험 :) –