Отримати товар у списку в Scala?


205

Як у світі ви отримуєте просто елемент в індексі i зі Списку в масштабі?

Я спробував get(i), і [i]- нічого не працює. Гугл повертає лише те, як "знайти" елемент у списку. Але я вже знаю індекс елемента!

Ось код, який не компілюється:

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

  }
  return null
}

Дивлячись на List api не допомагає, оскільки мої очі просто перехрещуються.


1
Ну добре, здається, що data.head спрацював ... Але все-таки це дає мені лише перший елемент, а не жоден у списку.
Андрій Дроздюк

Використовуйте застосовувані риси Seq (індекс), якщо ви впевнені, що індекс не виходить за межі. scala-lang.org/api/current / ...
Beezer

data.drop (i) .head працює над доступом до i-го елемента
Vinay

@Vinay Це дорога операція. Тож слід уникати "drop (i) .head".
Shubham Agrawal

Відповіді:


305

Використовуйте дужки:

data(2)

Але вам не дуже хочеться робити це зі списками дуже часто, оскільки пов'язані списки потребують часу для переходу. Якщо ви хочете індексувати колекцію, використовуйте Vector(незмінний) або ArrayBuffer(змінний) або можливо Array(що є лише масивом Java, за винятком того, що ви знову індексуєте його (i)замість [i]).


1
В основному я шукаю щось на зразок ArrayList в Java. Я думаю, непорушний був би теж добре.
Андрій Дроздюк

1
ArrayBufferпрацює як ArrayList. Vectorпрацює як непорушний - ArrayListви можете читати, але ви не можете писати, не створюючи нового.
Рекс Керр

Як щодо підлістового списку? Наприклад, в java я роблю "data.subList (0, index)".
Андрій Дроздюк

Не забудьте, я це отримав - це "шматочок"! Чи можу я перетворити ArrayBuffer у вектор? Або є більш загальний тип, з якого я можу повернутися з методів? Наприклад, у Java я б повернув інтерфейс List.
Андрій Дроздюк

1
Ви можете перетворити ArrayBufferна IndexedSeqкористування .toIndexedSeq; IndexedSeqє більш родовим типом. (У цьому випадку він фактично виявляється реалізованим як a Vector.) IndexedSeq- це супертип колекцій, які розумно індексувати. Також зауважте, що ви могли б зробити Vector() ++ myArrayBuffer, що буде працювати майже для будь-якої колекції (з обох боків). ++будує нову колекцію з двох вказаних вами, зберігаючи тип ліворуч. Vector()є порожнім вектором, тож він створює те, що ви хочете.
Рекс Керр

121

Більш безпечним є використання, liftщоб ви могли отримати значення, якщо воно існує, і вийти з ладу, якщо цього немає.

data.lift(2)

Це поверне "None", якщо список недостатньо довгий для надання цього елемента, і Some (значення), якщо він є.

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

Щоразу, коли ви виконуєте операцію, яка може не вдатися таким чином, чудово використовувати Option і отримати систему типу, щоб переконатися, що ви обробляєте випадок, коли елемент не існує.

Пояснення:

Це працює, тому що Список apply(який цукрує просто дужки, наприклад l(index)) - це як часткова функція, яка визначається там, де список має елемент. List.liftСпосіб включає часткову applyфункцію (функцію , яка визначена тільки для деяких входів) в нормальну функцію (певну для будь-якого вхідного сигналу) по суті обгорткового результату в якості опції.


11
Підйомник прекрасний. Я можу уникнути помилок arrayIndexOutOfBound, не перевіряючи розмір масиву ..
Naveen Sachar

9

Чому дужки?

Ось цитата з книжкового програмування в масштабі .

Ще одна важлива ідея, проілюстрована на цьому прикладі, дасть вам зрозуміти, чому масиви мають скоби в скобках у Scala. У Scala менше спеціальних випадків, ніж у Java. Масиви - це просто екземпляри класів, як і будь-який інший клас у Scala. Якщо ви застосуєте дужки, що оточують одне або більше значень до змінної, Scala перетворить код у виклик методу з назвою застосовувати до цієї змінної. Отже, HelloStrings (i) перетворюється на greeStrings.apply (i). Таким чином, доступ до елемента масиву в Scala - це просто виклик методу, як і будь-який інший. Цей принцип не обмежується масивами: будь-яке застосування об'єкта до деяких аргументів у дужках буде перетворено на виклик методу застосувати. Звичайно, це складатиметься лише в тому випадку, якщо цей тип об'єкта фактично визначає метод застосування. Тож це не особливий випадок; це загальне правило.

Ось кілька прикладів, як витягнути певний елемент (перший елем у цьому випадку) за допомогою функціонального стилю програмування.

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

2

Будь ласка, використовуйте дужки () для доступу до списку елементів list_name (індекс)


0

Це найкращий спосіб доступу до даних Списку через індекс сьогодні:

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

Але як Рекс Керр згадувався вище: Якщо ви використовуєте індекси, вам слід розглянути можливість використання Vector замість списку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.