2013-10-13 4 views
0

Извините за несколько общее название, если у кого есть лучшее предложение, пожалуйста, дайте мне знать.Получите массив из 3 упорядоченных значений, предпочитая указанное значение

В основном я пишу пользовательский вид в виде списка, в котором я хочу показать только 3 оценки. Если возможно, он покажет текущий счет пользователя в середине, но если пользователь находится в верхней или нижней части списка, он должен по-прежнему показывать 3 балла, но он отображает других пользователей выше или ниже списка.

например.

  1. Me (Если я сверху, а затем показать 2 ниже)
  2. Пользователь 1
  3. Пользователь 2

или

  1. Пользователь 1
  2. Me (обычный случай где я нахожусь в середине двух оценок)
  3. Пользователь 2

или

  1. Пользователь 1
  2. Пользователь 2
  3. Me (Если я донную показывают две оценки выше меня)

У меня есть функция написано, что делает первая часть этого, но не учитывает крайние случаи, с которыми я борюсь. Кто-нибудь может посоветовать?

-(void)getNearbyScores:(int)score{ 
    GCLeaderboardScore *closestScoreAbove = nil; //Custom container for GC properties 
    GCLeaderboardScore *closestScoreBelow = nil; //Contains playerID, score, alias etc 

    if ([playerScores count] == 0){ //playerScores is an NSMutableDictionary 
     return; 
    } 

    for (NSString* key in playerScores) { 

     GCLeaderboardScore *playerScore = (GCLeaderboardScore *)[playerScores objectForKey:key]; 
     if ((closestScoreAbove == nil || closestScoreAbove->score > playerScore->score) && playerScore->score > score){ 
      closestScoreAbove = playerScore; 
     } 
     else if ((closestScoreBelow == nil || closestScoreAbove->score < playerScore->score) && playerScore->score < score){ 
      closestScoreBelow = playerScore; 
     } 
    } 

    me->score = score; 
    me->rank = 1; 
    if (closestScoreAbove != nil) { 
     me->rank = closestScoreAbove->rank + 1; 
     nearbyScores = [NSMutableArray arrayWithObjects: closestScoreAbove, me, closestScoreBelow, nil]; 
    } 
    else { 
     nearbyScores = [NSMutableArray arrayWithObjects: me, closestScoreBelow, nil]; 
    } 
} 
+0

Используя двоичное дерево поиска, довольно легко изменить алгоритм поиска, чтобы выполнить именно то, что вам нужно. – Justin

+0

Вместо того, чтобы найти 1 балл чуть выше и 1 балл чуть ниже, попробуйте найти 2 балла чуть выше и 2 балла чуть ниже «мой счет». –

+0

@AbhishekBansal Я думал об этом, но проблема в том, что если я это сделаю, тогда есть шанс (я думаю), я не найду второй ближайший результат, если я не зациклирую дважды, что я не хочу делать – Chris

ответ

1

Предполагая, что есть meGCLeaderboardScore объект, ниже метод должен возвращать массив с желаемыми GCLeaderboardScore объектов (непроверенных):

-(NSArray *)getNearbyScores { 

    if(playerScores.count==0) return nil; 

    // Create an array sorted by score 
    NSArray *sortedByScore=[playerScores sortedArrayUsingComparator: ^(id object1, id object2) { 
     GCLeaderboardScore *score1=object1; 
     GCLeaderboardScore *score2=object2; 

     if(score1->score < score2->score) return NSOrderedAscending; 
     if(score1->score > score2->score) return NSOrderedDescending; 

     return NSOrderedSame; 
    }]; 

    // Find index of me 
    NSUInteger idx=[sortedByScore indexOfObject:me]; 

    // If me not found, return nil 
    if(idx==NSNotFound) return nil; 

    // Ideally we want to show the player before and behind 
    idx=MAX(0,(NSInteger)idx-1); 

    // maxIdx will be idx+2 or index of last object if lower 
    NSUInteger maxIdx=MIN(sortedByScore.count-1,idx+2); 

    // In case we are last, show two previous results (if array large enough) 
    if (maxIdx > 3) 
       idx=MAX(0,maxIdx-3); 

    // And return the objects, may be 1..3 objects 
    return [sortedByScore subarrayWithRange:NSMakeRange(idx,maxIdx-idx+1)]; 
} 
+0

Это выглядит довольно круто.Мой playerScores - это 'NSMutableDictionary', но может ли это быть аналогично этому? – Chris

+0

Работает отлично от последней строки, не зная, в чем проблема, поскольку я не получаю ошибку как таковую ... 'nearbyScores = [sortedByScore subarrayWithRange: NSMakeRange (idx, maxIdx - idx + 1)];' – Chris

+0

Ah нашел это : «Завершение приложения из-за неперехваченного исключения» NSRangeException », причина:« *** - [NSArray subarrayWithRange:]: диапазон {4294967294, 4} выходит за пределы [0 .. 1] ' ' – Chris

0

Я предполагаю, что у вас есть массив баллов. (Фактическая реализация может быть адаптирована к коду)

Initialize: 
firstScoreAbove = VERY_LARGE_SCORE; secondScoreAbove = VERY_LARGE_SCORE + 1; 
firstScoreBelow = -1; secondScoreBelow = -2; 

Scan the array elements. 
if (newScore > myScore) { 
    if (newScore < firstScoreAbove) { 
    secondScoreAbove = firstScoreAbove; 
    firstScoreAbove = newScore; 
    } else if (newScore < secondScoreAbove) { 
    secondScoreAbove = newScore; 
    } 
} else { 
    // similarly for below. 
} 

После сканирования
Если firstScoreAbove не изменился, то myScore является верхним и вывести два ниже оценки.
Если firstScoreBelow не изменился, то myScore является самым низким и выводит два вышеуказанных показателя.
Else Output firstScoreAbove, myScore, firstScoreBelow.

+0

Это близко, но не работает на крайних случаях. Я боюсь – Chris

+0

@Chris. Как это происходит из-за красных случаев? Возможно, я ошибся, но мне жаль, что это не ясно. –

Смежные вопросы