Scala Получить первый и последний элементы списка с использованием сопоставления с образцом

Я делаю сопоставление шаблонов в списке. Есть ли в любом случае доступ к первому и последнему элементам списка для сравнения?

Я хочу сделать что-то вроде..

case List(x, _*, y) if(x == y) => true

или

case x :: _* :: y =>

или что-то подобное... где x и y - это первый и последний элементы списка.

Как я могу это сделать... любые идеи?

Ответ 1

Используйте стандартные : + и +: экстракторы из пакета scala.collection


ОРИГИНАЛЬНЫЙ ОТВЕТ

Определите пользовательский объект-экстрактор.

object :+ {
  def unapply[A](l: List[A]): Option[(List[A], A)] = {
    if(l.isEmpty)
      None
    else 
      Some(l.init, l.last)
  }
}

Может использоваться как:

val first :: (l :+ last) = List(3, 89, 11, 29, 90)
println(first + " " + l + " " + last) // prints 3 List(89, 11, 29) 90

(Для вашего случая: case x :: (_ :+ y) if(x == y) => true)

Ответ 2

Если вы пропустили очевидное:

case list @ (head :: tail) if head == list.last => true

Здесь находится часть head::tail, поэтому вы не соглашаетесь на пустой список.

Ответ 3

просто:

case head +: _ :+ last => 

например:

scala> val items = Seq("ham", "spam", "eggs")
items: Seq[String] = List(ham, spam, eggs)

scala> items match {
     |   case head +: _ :+ last => Some((head, last))
     |   case List(head) => Some((head, head))
     |   case _ => None
     | }
res0: Option[(String, String)] = Some((ham,eggs))

Ответ 4

Давайте разберемся с концепцией, связанной с этим вопросом, между '::', '+:' и ': +' есть разница:

1-й оператор:

' :: ' - это правильный ассоциативный оператор, который работает специально для списков

scala> val a :: b :: c = List(1,2,3,4)
a: Int = 1
b: Int = 2
c: List[Int] = List(3, 4)

2-й оператор:

' +: ' - это также правильный ассоциативный оператор, но он работает на seq, который является более общим, чем просто список.

scala> val a +: b +: c = List(1,2,3,4)
a: Int = 1
b: Int = 2
c: List[Int] = List(3, 4)

3-й оператор:

' : + ' - это также левый ассоциативный оператор, но он работает на seq, который является более общим, чем просто список

scala> val a :+ b :+ c = List(1,2,3,4)
a: List[Int] = List(1, 2)
b: Int = 3
c: Int = 4

Ассоциативность оператора определяется оператором последнего символа. Операторы, оканчивающиеся на двоеточие: ассоциативны справа. Все остальные операторы левоассоциативны.

Левый-ассоциативная бинарная операция е1; оп; е2 интерпретируется как e1.op (е2)

Если op является ассоциативным справа, эта же операция интерпретируется как {val x = e1; e2.op(x) }, where x is a fresh name. e2.op(x)}, где x - новое имя.

Теперь приходит ответ на ваш вопрос: так что теперь, если вам нужно получить первый и последний элемент из списка, пожалуйста, используйте следующий код

scala> val firstElement +: b :+ lastElement = List(1,2,3,4)
firstElement: Int = 1
b: List[Int] = List(2, 3)
lastElement: Int = 4