Как извлечь список из карты в Scala по условиям?

У меня есть карта, состоящая из строк и списков кортежей:

Map[String, List[(String, Int]]

Некоторые примеры линий на карте выглядят так:

"test1", List(("apple", 0), ("pear", 1), ("banana", 0))

"test2", List(("green", 1), ("yellow", 1), ("red", 0))

"test3", List(("monday", 0), ("tuesday", 1), ("wednesday", 0))

каков наилучший способ извлечь список первых строк в каждой строке, только если список кортежей содержит более 1 значения, равного 0?

Другими словами, мне нужен список, содержащий «test1» и «test2», поскольку эти 2 строки являются единственными строками, которые содержат более 1 «0» в своем списке кортежей.

Что вы пробовали? Почему это не сработало? - Подсказки: вы хотите collect + exists

Luis Miguel Mejía Suárez 04.04.2022 21:36

Но «test2» имеет больше 1, чем 0, поэтому, может быть, вместо этого следует напечатать test3?

Goosefand 04.04.2022 21:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша отправная точка будет либо collect, либо filter; оба метода полезны, когда у вас есть коллекция и вы хотите создать новую коллекцию с некоторыми условными условиями.

Ваше условие, как описано, звучит как прецедент для метода count, который определен практически для каждого типа коллекции в стандартной библиотеке.

Это должно сработать...

theMapFromYourExample
  .collect { case (key, list) if list.count(_._2 == 0) > 1 => key }
  .toList

... но есть некоторые соображения:

  • .collect и toList создадут новые целые коллекции. Объединение их вместе означает, что вы тратите немного памяти и процессорного времени на создание промежуточной коллекции, которая просто отправляется прямо в сборку мусора, как только ваше выражение завершено. Чтобы избежать выделения памяти для всей промежуточной коллекции, вы можете использовать шаблон Вид, доступный через метод .view в большинстве коллекций.
  • .count равен O(N) размеру списка, так как ему нужно проверить каждый элемент в списке, чтобы увидеть, соответствует ли он вашему условному выражению. Поскольку вам нужно только, чтобы счет был «по крайней мере» определенного значения, вы можете прекратить считать раньше, если вы превысите 1. Метод lengthCompare полезен для такого рода вещей.

Итак, вот примерно тот же код, использующий «представления» для повышения эффективности:

def hasAtLeastTwoZeroes(list: List[(String, Int)]) = {
  list
   .view // lets us call `.filter` without allocating a new List
   .filter(_._2 == 0) // apply conditional: value is 0
   .lengthCompare(1) > 0 // like saying `.length > 1`, but is O(1), not O(N)
}

theMapFromYourExample
  .view // lets us call `collect` without allocating an intermediate collection
  .collect { case (key, list) if hasAtLeastTwoZeroes(list) => key }
  .toList // builds a List from the collected view

Обновлять, как отметил Луис в комментариях, в Scala 2.13 добавлен метод sizeIs, который имеет более удобный интерфейс, чем lengthCompare

Вы можете использовать sizeIs > 1 вместо lengthCompare(1) > 0, и он все равно остановится раньше.

Luis Miguel Mejía Suárez 04.04.2022 22:48

@LuisMiguelMejíaSuárez, очень круто. Похоже на функции Scala 2.13, о которых я не знал (я все еще застрял на 2.12 по работе).

Dylan 05.04.2022 00:13

Другие вопросы по теме