Как выполнить сопоставление с шаблоном vararg? - PullRequest
13 голосов
/ 16 февраля 2010

У меня есть набор классов case, подобных этому

abstract class Shape  
case class Rectangle(width: Int, height: Int) extends Shape  
case class Location(x: Int, y: Int, shape: Shape) extends Shape  
case class Circle(radius: Int) extends Shape  
case class Group(shape: Shape*) extends Shape

, где в основном группа представляет собой массив фигур. Мне нужно определить метод размера для вычисления размеров для прямоугольника, круга и местоположения его просто вернуть. Но у меня есть трудности для группы.

object size extends Shape{  
  def size(s: Any) : Int = s match {  
    case Rectangle(x,y) => 1  
    case Group  // how to do it? Also having case Group(shape : Shape*) gives an error  
    case Circle(r) => 1    
    case Location(x,y,shape) => 1   
  }  
}  

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

Ответы [ 5 ]

17 голосов
/ 16 февраля 2010

Любой из них будет работать, второй, вероятно, предпочтительнее, если немного странно на первый взгляд.См. 8.1.9 Последовательности паттернов из Справочника Scala .

case g: Group => g.shape.map(size(_)).sum

case Group(ss @ _*) => ss.map(size(_)).sum

Используется Scala 2.8.sum может не работать на старых версиях.

8 голосов
/ 16 февраля 2010

Синтаксис для сопоставления с образцом vararg несколько странный .

def size(s: Shape) : Int = s match{
  case Rectangle(x,y) => 1
  case Circle(r) => 1
  case Location(x,y,shape) => 1
  case Group(shapes @ _*) => (0 /: shapes) { _ + size(_) }
}

Обратите внимание, что в последней строке вы суммируете размеры всех подэлементов shapes, начинающихся с нуля, используя /: -обращение для фальцов.


Как работает folds : Folds аккумулирует элементы последовательности, используя заданную функцию.

Таким образом, чтобы вычислить сумму списка, мы должны написать (в стиле Хаскеля)

fold (\total element -> total + element) 0 list

, который объединит все элементы списка с заданной функцией сложения, начинающейся с 0 (и, следовательно, вычислит сумму).

В Scala мы можем написать это так:

(0 /: list) { (total, element) => total + element }

, который можно упростить до

(0 /: list) { _ + _ }
2 голосов
/ 16 февраля 2010

Первый шаг - выяснить, что вы имеете в виду. Два наиболее очевидных варианта - это общая площадь, охватываемая всеми фигурами, и минимальный прямоугольник, содержащий их все. Если для кругов вы возвращаете реальную область, то вам, вероятно, придется идти с реальной областью.

Нет закрытого способа ответить на этот вопрос. Я мог бы подумать о том, чтобы бросить тысячу случайных дротиков в минимальный охватывающий прямоугольник и оценить площадь как процент дротиков, попавших в занятую точку. Является ли оценка приемлемым ответом?

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

1 голос
/ 24 февраля 2010

Для размера местоположения следует углубиться, чтобы получить размер, поскольку фигура может быть группой, которая вызывает большее число

case Location (x, y, shape) => размер (shape)

То есть, если размер - это число фигур в фигуре

0 голосов
/ 16 февраля 2010

case g: Group => g.shape.map (size (_)). Sum

case Group (ss @ *) => ss.map (размер ()) .sum

оба из них дают значение ошибки, сумма которого не является членом Seq [Int]
Однако этот параметр работает
case Group (shape @ _ *) => (0 /:формы) {_ + размер (_)

...