Obtener artículo en la lista en Scala?


205

¿Cómo en el mundo obtienes solo un elemento en el índice i de la Lista en scala?

Lo intenté get(i)y [i]... nada funciona. Buscar en Google solo devuelve cómo "encontrar" un elemento en la lista. ¡Pero ya sé el índice del elemento!

Aquí está el código que no se compila:

def buildTree(data: List[Data2D]):Node ={
  if(data.length == 1){
      var point:Data2D = data[0]  //Nope - does not work

  }
  return null
}

Mirar la API de la Lista no ayuda, ya que mis ojos se cruzan.


1
Bueno, bueno, parece que data.head funcionó ... Pero aún así eso solo me da el primer elemento, ninguno en la lista.
Andriy Drozdyuk

Utilice los rasgos Seq aplicar (índice) si está seguro de que el índice no está fuera de los límites. scala-lang.org/api/current/…
Beezer

data.drop (i) .head funciona para acceder al elemento i-th
Vinay

@Vinay Esa es una operación costosa. Entonces uno debe evitar "drop (i) .head".
Shubham Agrawal

Respuestas:


306

Use paréntesis:

data(2)

Pero realmente no desea hacer eso con listas muy a menudo, ya que las listas enlazadas tardan en recorrerlas. Si desea indexar en una colección, use Vector(inmutable) o ArrayBuffer(mutable) o posiblemente Array(que es solo una matriz de Java, excepto que nuevamente lo indexa con en (i)lugar de [i]).


1
Básicamente estoy buscando algo como ArrayList en Java. Supongo que inmutable también estaría bien.
Andriy Drozdyuk

1
ArrayBufferfunciona como ArrayList. Vectorfunciona como un inmutable: ArrayListpuedes leer, pero no puedes escribir sin crear uno nuevo.
Rex Kerr

¿Qué tal una sublista? Por ejemplo, en Java hago "data.subList (0, index)".
Andriy Drozdyuk

No importa, lo tengo, ¡es "rebanada"! ¿Puedo convertir ArrayBuffer a Vector? ¿O hay un tipo más genérico que puedo devolver de los métodos? Por ejemplo, en Java, devolvería la interfaz List.
Andriy Drozdyuk

1
Puede convertir ArrayBuffera un IndexedSequso .toIndexedSeq; IndexedSeqEs el tipo más genérico. (En este caso, resulta que se implementa como a Vector.) IndexedSeqEs el supertipo de colecciones a las que es razonable indexar. Además, tenga en cuenta que podría hacerlo Vector() ++ myArrayBuffer, lo que funcionará para casi cualquier colección (en cualquier lado). ++crea una nueva colección a partir de las dos que especifique, conservando el tipo de la de la izquierda. Vector()es el vector vacío, por lo que produciría lo que quieres.
Rex Kerr

121

Es más seguro usarlo liftpara que pueda extraer el valor si existe y fallar con gracia si no es así.

data.lift(2)

Esto devolverá None si la lista no es lo suficientemente larga como para proporcionar ese elemento, y Some (value) si lo es.

scala> val l = List("a", "b", "c")
scala> l.lift(1)
Some("b")
scala> l.lift(5)
None

Cada vez que realiza una operación que puede fallar de esta manera, es genial usar una Opción y obtener el sistema de tipos para ayudar a asegurarse de que está manejando el caso donde el elemento no existe.

Explicación:

Esto funciona porque la Lista apply(que azucara solo entre paréntesis, por ejemplo l(index)) es como una función parcial que se define donde la lista tiene un elemento. El List.liftmétodo convierte la applyfunción parcial (una función que solo se define para algunas entradas) en una función normal (definida para cualquier entrada) básicamente envolviendo el resultado en una Opción.


11
El ascensor es hermoso. Puedo evitar los errores de arrayIndexOutOfBound, sin verificar el tamaño de la matriz ..
Naveen Sachar

9

¿Por qué paréntesis?

Aquí está la cita de la programación del libro en scala .

Otra idea importante ilustrada en este ejemplo le dará una idea de por qué se accede a las matrices con paréntesis en Scala. Scala tiene menos casos especiales que Java. Las matrices son simplemente instancias de clases como cualquier otra clase en Scala. Cuando aplica paréntesis alrededor de uno o más valores a una variable, Scala transformará el código en una invocación de un método llamado aplicar en esa variable. Entonces greetStrings (i) se transforma en greetStrings.apply (i). Por lo tanto, acceder a un elemento de una matriz en Scala es simplemente una llamada a un método como cualquier otro. Este principio no se limita a las matrices: cualquier aplicación de un objeto a algunos argumentos entre paréntesis se transformará en una llamada al método de aplicación. Por supuesto, esto solo se compilará si ese tipo de objeto realmente define un método de aplicación. Entonces no es un caso especial; Es una regla general.

Aquí hay algunos ejemplos de cómo extraer cierto elemento (primer elemento en este caso) usando un estilo de programación funcional.

  // Create a multdimension Array 
  scala> val a = Array.ofDim[String](2, 3)
  a: Array[Array[String]] = Array(Array(null, null, null), Array(null, null, null))
  scala> a(0) = Array("1","2","3")
  scala> a(1) = Array("4", "5", "6")
  scala> a
  Array[Array[String]] = Array(Array(1, 2, 3), Array(4, 5, 6))

  // 1. paratheses
  scala> a.map(_(0))
  Array[String] = Array(1, 4)
  // 2. apply
  scala> a.map(_.apply(0))
  Array[String] = Array(1, 4)
  // 3. function literal
  scala> a.map(a => a(0))
  Array[String] = Array(1, 4)
  // 4. lift
  scala> a.map(_.lift(0))
  Array[Option[String]] = Array(Some(1), Some(4))
  // 5. head or last 
  scala> a.map(_.head)
  Array[String] = Array(1, 4)


-1

Esta es la forma preferida de acceder a los datos de una Lista a través del índice hoy en día:

scala> val list = List("a","b","c")
scala> list.get(1)
Some("b")
scala> list.get(5)
None

Pero al igual que Rex Kerr mencionado anteriormente: Si está utilizando índices, debería considerar usar Vector en lugar de una Lista.


value get no es miembro de List [String]
Greenev hace
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.