Как выполнить сопоставление образцов с классами классов vararg?

У меня есть набор классов 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   
  }  
}  

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

Ответ 1

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

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

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

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

Ответ 2

Синтаксис для сопоставления шаблонов 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 work: Складывает элементы последовательности, используя заданную функцию.

Итак, чтобы вычислить сумму списка, мы будем писать (стиль Haskell)

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

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

В Scala мы можем записать его следующим образом:

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

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

(0 /: list) { _ + _ }

Ответ 3

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

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

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

Ответ 4

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

case Location (x, y, shape) = > size (shape)

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

Ответ 5

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

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

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