2015-02-07 2 views
1

Запуск моего первого проекта с помощью Scala: рамки для покера.Два метода в одной скале

Поэтому у меня есть следующий класс

class Card(rank1: CardRank, suit1: Suit){ 
val rank = rank1 
val suit = suit1 
} 

и объект Utils, который содержит два метода, которые делают почти то же самое: они подсчитывают количество карт для каждого ранга или костюм

def getSuits(cards: List[Card]) = { 

def getSuits(cards: List[Card], suits: Map[Suit, Int]): (Map[Suit, Int]) = { 
    if (cards.isEmpty) 
    return suits 

    val suit = cards.head.suit 
    val value = if (suits.contains(suit)) suits(suit) + 1 else 1 
    getSuits(cards.tail, suits + (suit -> value)) 

} 

getSuits(cards, Map[Suit, Int]()) 

} 


def getRanks(cards: List[Card]): Map[CardRank, Int] = { 

def getRanks(cards: List[Card], ranks: Map[CardRank, Int]): Map[CardRank, Int] = { 
    if (cards isEmpty) 
    return ranks 

    val rank = cards.head.rank 
    val value = if (ranks.contains(rank)) ranks(rank) + 1 else 1 
    getRanks(cards.tail, ranks + (rank -> value)) 
} 

getRanks(cards, Map[CardRank, Int]()) 
} 

Is я могу каким-то образом «объединить» эти два метода в одном «поле/метод-как-параметр»?

Благодаря

ответ

3

Да, это потребует функции высокого порядка (то есть, функция, которая принимает функцию в качестве параметра) и параметры типа/Генеричность

def groupAndCount[A,B](elements: List[A], toCount: A => B): Map[B, Int] = { 
    // could be your implementation, just note key instead of suit/rank 
    // and change val suit = ... or val rank = ... 
    // to val key = toCount(card.head) 
} 

затем

def getSuits(cards: List[Card]) = groupAndCount(cards, {c : Card => c.suit}) 
def getRanks(cards: List[Card]) = groupAndCount(cards, {c: Card => c.rank}) 

Вы делаете не нужен параметр типа A, вы можете заставить метод работать только на Карте, но это было бы очень жаль.

Для дополнительного кредита, вы можете использовать два списка параметров, и имеют

def groupAndCount[A,B](elements: List[A])(toCount: A => B): Map[B, Int] = ... 

что немного особенность Скале с умозаключения типа, если вы со списками двух параметров, вам не нужно будет вводить аргумент карты при определении функции:

def getSuits(cards: List[Card]) = groupAndCount(cards)(c => c.suit) 

или просто

def getSuits(cards: List[Card] = groupAndCount(cards)(_.suit) 

Конечно, библиотека может помочь вам с реализацией

def groupAndCount[A,B](l: List[A])(toCount: A => B) : Map[A,B] = 
    l.groupBy(toCount).map{case (k, elems) => (k, elems.length)} 

хотя ручная реализация может быть немного быстрее.

минорной ноте, карта должна быть объявлена ​​case class:

case class Card(rank: CardRank, suit: Suit) 
// declaration done, nothing else needed 
Смежные вопросы