Scala'daki listeden öğe al?


205

Dünyada nasıl scala'daki Listeden i dizinindeki bir öğeyi elde edersiniz ?

Denedim get(i)ve [i]- hiçbir şey çalışmıyor. Google, yalnızca listedeki bir öğenin nasıl "bulunacağını" döndürür. Ama elementin indeksini zaten biliyorum!

Derlemeyen kod şöyledir:

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

  }
  return null
}

Listeye bakmak api yardımcı olmuyor, gözlerim kesiştiği için.


1
Eh, data.head çalıştı gibi görünüyor ... Ama yine de bana sadece ilk elementi veriyor, listedeki herhangi bir şeyi değil.
Andriy Drozdyuk

Dizinin sınırların dışında olmadığından eminseniz , Sıra özellikleri uygulayın (dizin) . scala-lang.org/api/current/...
Beezer

data.drop (i) .head i-th öğesine erişmek için çalışır
Vinay

@Vinay Bu pahalı bir işlemdir. Bu yüzden "drop (i) .head" den kaçınmalısınız.
Shubham Agrawal

Yanıtlar:


305

Parantez kullanın:

data(2)

Ancak bunu, listelerle sık sık yapmak istemezsiniz, çünkü bağlantılı listelerin geçişi zaman alır. Bir koleksiyona indekslemek istiyorsanız, Vector(değiştirilemez) veya ArrayBuffer(değiştirilebilir) veya muhtemelen Array(sadece bir Java dizisidir, (i)bunun yerine bununla birlikte dizine eklemeniz dışında [i]) kullanın.


1
Temelde Java ArrayList gibi bir şey arıyorum. Bence değişmez de iyi olur.
Andriy Drozdyuk

1
ArrayBuffergibi çalışır ArrayList. Vectordeğişmez gibi çalışır - ArrayListokuyabilirsiniz, ancak yeni bir tane oluşturmadan yazamazsınız.
Rex Kerr

Bir alt listeye ne dersiniz? Örneğin java'da "data.subList (0, index)" yapıyorum.
Andriy Drozdyuk

Boşver, anladım - bu "dilim"! ArrayBuffer'ı Vector'a dönüştürebilir miyim? Yoksa yöntemlerden dönebileceğim daha genel bir tür var mı? Örneğin Java'da Liste arayüzünü döndürürdüm.
Andriy Drozdyuk

1
Sen dönüştürebilirsiniz ArrayBufferbir karşı IndexedSeqkullanarak .toIndexedSeq; IndexedSeqdaha genel tiptir. (Bu durumda aslında a Vector. Olarak uygulandığı ortaya çıkar .) IndexedSeqDizine eklenmesi makul olan koleksiyonların süper tipidir. Ayrıca, Vector() ++ myArrayBufferhemen hemen her koleksiyonda (her iki tarafta) çalışacak olan yapabileceğinizi unutmayın . ++soldaki koleksiyon türünü koruyarak belirttiğiniz ikisinden yeni bir koleksiyon oluşturur. Vector()boş vektördür, bu yüzden istediğinizi üretir.
Rex Kerr

121

Daha güvenli kullanmaktır, liftböylece değeri varsa ayıklayabilirsiniz ve yoksa incelikle başarısız olabilirsiniz.

data.lift(2)

Liste bu öğeyi sağlayacak kadar uzun değilse, Hiçbiri ve varsa bazı (değer) döndürür.

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

Bu şekilde başarısız olabilecek bir işlem gerçekleştirdiğinizde, öğenin var olmadığı durumu ele aldığınızdan emin olmanıza yardımcı olmak için bir Seçenek kullanmak ve tür sistemini kullanmak harika olur.

Açıklama:

Bunun nedeni apply, List'in (örneğin parantez içine alınan şekerler l(index)) listenin bir öğesi olduğu her yerde tanımlanan kısmi bir işlev gibi olmasıdır. List.liftYöntem, kısmi döner applyfonksiyonu temel olarak Opsiyon sonucu sararak (herhangi bir giriş için) olan normal bir işlev (sadece bazı girdilerin için tanımlanan bir fonksiyonu).


11
Asansör güzel. Dizi boyutunu kontrol etmeden, arrayIndexOutOfBound hatalarını önleyebilirsiniz ..
Naveen Sachar

9

Neden parantez?

İşte scala'da kitap programlamadan alıntı .

Bu örnekle gösterilen bir başka önemli fikir, Scala'daki parantezlerle dizilere neden erişildiğine dair fikir verecektir. Scala'nın Java'dan daha az özel vakası var. Diziler Scala'daki diğer sınıflar gibi sınıfların örnekleridir. Bir veya daha fazla değeri çevreleyen parantezleri bir değişkene uyguladığınızda, Scala kodu bu değişken üzerinde uygula adlı bir yöntemin çağrılmasına dönüştürür. Böylece greetStrings (i) greetStrings.apply (i) biçimine dönüştürülür. Bu nedenle Scala'da bir dizinin bir elemanına erişmek, diğerleri gibi bir yöntem çağrısıdır. Bu ilke dizilerle sınırlı değildir: bir nesnenin parantez içindeki bazı bağımsız değişkenlere herhangi bir uygulaması bir uygulama yöntemi çağrısına dönüştürülecektir. Elbette bu sadece bu tür bir nesne gerçekten bir uygulama yöntemi tanımladığında derlenir. Bu özel bir durum değil; genel bir kuraldır.

Aşağıda, işlevsel programlama stilini kullanarak belirli öğelerin (bu durumda ilk elem) nasıl çekileceğine dair birkaç örnek verilmiştir.

  // 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)


0

Günümüzde bir Listenin verilerine endeks yoluyla erişmenin tercih edilen yolu:

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

Ancak yukarıda bahsedilen Rex Kerr gibi: Dizin kullanıyorsanız, Liste yerine Vector kullanmayı düşünmelisiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.