case class Student(id:String, name:String, teacher:String )
val myList = List( Student("1","Ramesh","Isabela"), Student("2","Elena","Mark"),Student("3","invalidKey","Someteacher"))
val a = myList.foreach( i=> (i.name -> i.teacher)).toMap.filter(i.name != "invalidKey")
У меня есть список кейс-класса студента. Я хочу построить карту ученика, учителя, имя которой (ключ карты) всегда будет уникальным. Предпочтительно карта может отфильтровывать определенное имя.
Вы можете использовать collect
вместо map
+ filter
Я не получаю элементы от итератора i . вот в чем проблема
Что ж, поскольку вы используете foreach
вместо map
, если вы проверите подписи типов и прочитаете документацию, станет ясно, почему это не сработает: scala-lang.org/api/current/scala/collection/immutable/List.html — В любом случае, все, что вам нужно, это: scastie.scala-lang.org/BalmungSan/mEEDnPQ0TcWAwE8lcz9EIg/2
Вы используете foreach, который возвращает Unit в качестве результата. Я бы предложил любой из этих 2 ниже. Первый, как упомянул Луис Мигель:
val myMap = myList.collect {
case student if student.name != "invalidKey" => student.name -> student.teacher
}.toMap
Или:
val myMap2 = myList.foldLeft[Map[String, String]](Map.empty) {
case (elementsMap, newElement) if newElement.name != "invalidKey" =>
elementsMap + (newElement.name -> newElement.teacher)
case (elementsMap, _) => elementsMap
}
Отличия:
Первый подход намного легче читать и короче (хотя короче не является преимуществом: D). Второй имеет меньше итераций (у первого есть еще одна итерация для преобразования в карту).
Вы можете просто добавить view
перед collect
, и теперь первый из них повторяется только один раз... но на самом деле это может быть медленнее для небольших коллекций; преждевременная оптимизация — корень всех зол.
Кстати, то, что я имел в виду под «имеет на одну итерацию меньше», заключается не в том, что у него лучший порядок алгоритма с точки зрения временной сложности, они оба считаются O (n).
@LuisMiguelMejíaSuárez, Интересно! Я этого не знал. вы можете отредактировать ответ :)
@LuisMiguelMejíaSuárez, я просмотрел представления, а также прочитал некоторые версии реальных исходных кодов и обнаружил, что это в значительной степени зависит от реализации SeqView. В некоторых версиях представление содержит конструктор типов, и когда вы хотите преобразовать список в карту, представление принудительно оценивается (что приводит к списку[...]), а затем преобразуется в карту (эта одна дополнительная итерация) . а в более новых версиях view избавляется от конструктора типов, а преобразование в карту выполняется с помощью Map.from(iterable)
(я не уверен, есть ли в этом дополнительная итерация). (остальная часть комментария в следующем).
В обоих случаях (обе реализации), я думаю, что второй подход (свертывание) займет меньше или равно первому (представление). Я прав?
Да, Views
до 2.13
в основном бесполезны, я в основном игнорирую их существование до 2.13
, и да, foldLeft
всегда должен быть как минимум таким же эффективным. Но опять же, чтобы на самом деле ответить, что нужно правильно оценивать производительность, лучше всего оптимизировать читаемость и заботиться о производительности только тогда, когда это действительно важно.
@LuisMiguelMejíaSuárez, я согласен, я недавно опубликовал вопрос на обмен стеками codereview, который касается именно этой темы (читабельность и т. д.). Не могли бы вы взглянуть?
Для этого вопроса я, вероятно, сначала посмотрел бы, предоставляет ли фс2 что-то, если нет, я бы использовал State
и traverse
из кошки.
Добавьте
toMap
в конце. и убериprintln