Сокращение списка карт до списка в ближайшем будущем - PullRequest
0 голосов
/ 24 февраля 2019

Я начал получать некоторое функциональное программирование несколько недель назад, и я пытаюсь выполнить отображение из списка карт в список с учетом определенного ключа в clojure.

Мой список карт выглядиткак: '({:a "a1" :b "b1" :c "c1"} {:a "a2" :b "b2" :c "c2"} {:a "a3" :b "b3" :c "c3"})

И вывод, который я пытаюсь получить: '("b1" "b2" "b3").

Я пробовал следующее:

(doseq [m maps]
  (println (list (get m :b))))

И мойвывод представляет собой список списков (что ожидается, когда я создаю список для каждой итерации).Итак, мой вопрос, как я могу сократить это до одного списка?

Обновление

Только что попробовал следующее:

(let [x '()]
  (doseq [m map]
    (conj x (get m :b))))

Однако,это все еще не работает.Я не понимаю, как я собирался добавлять элементы в пустой список

Ответы [ 3 ]

0 голосов
/ 24 февраля 2019

У вас правильная идея, но вы используете неправильную функцию.doseq предназначен только для побочных эффектов и всегда возвращает nil.Функция, которую вы ищете - for, которая принимает последовательность в качестве входных данных и возвращает другую последовательность в качестве выходных данных.Я обычно предпочитаю for аналогичному map, так как for позволяет назвать переменную цикла:

(def data-list
  [{:a "a1" :b "b1" :c "c1"}
   {:a "a2" :b "b2" :c "c2"}
   {:a "a3" :b "b3" :c "c3"}])

(let [result (vec (for [item data-list]
                     (:b item)))]
  (println result)   ; print result
  result)            ; return result from `let` expression

result => ["b1" "b2" "b3"]

Если вместо этого вы сделаете следующее:

(println
  (doseq [item data-list]
    (println (:b item))))

, вы можетесм. разницу с doseq против for:

b1    ; loop item #1
b2    ; loop item #2
b3    ; loop item #3
nil   ; return value of doseq

Для получения подробной информации см. https://www.braveclojure.com/ и купите хорошую книгу (или 5), например Getting Clojure и т. д.

0 голосов
/ 27 февраля 2019
(doseq [m maps]
  (println (list (get m :b))))

В двух коротких строках вы нарушаете несколько общих правил функционального программирования:

  • Передача данных в функцию в качестве аргументов, а не ссылок на глобальные переменные.
  • Не печатать результаты вычислений.Верните их в качестве значения функции.
  • Избегайте механизмов, таких как doseq, которые работают с побочными эффектами.

Несмотря на это, вы были не слишком далеки от решения.doseq по сути является версией for, которая отбрасывает свой результат.Если мы заменим doseq на for и избавимся от println и list, мы получим

=> (for [m maps] (get m :b))
("b1" "b2" "b3")

Но Простое использование Артуром Ульфельдтом map лучше.

0 голосов
/ 24 февраля 2019

Это очень распространенный шаблон в рабочем коде Clojure, так что это хорошее место для изучения.В общем, ознакомьтесь с документами по последовательностям https://clojure.org/reference/sequences и, столкнувшись с подобной задачей, посмотрите, какой шаблон лучше всего подходит, и изучите функции в этой группе.В данном случае это «Обработать каждый элемент из seq для создания нового seq», и первый элемент в списке будет map

, ваш пример может выглядеть как

 (map :b my-data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...