Функция поиска в clojure

Вот еще одна возможность, использующая естественно рекурсивный характер JSON.stringify:

const input = [{"Attr":[{"power":{"p1":"str","t3":"str"},"light":[{"test":"str"},{"test2":[{"t4":"str"}]}]}]},{"Attr1":[{"power1":{"p2":"str","t5":"str"},"light1":[{"test3":"str"},{"test_x":[{"t_x":"str"},{"t_y":[{"t_y1":"str"}]}]}]}]}];

const output = [];
JSON.stringify(input, (key, val) => {
  if (val === 'str') output.push(key);
  return val;
});
console.log(output);

1
задан A.G 19 January 2019 в 19:59
поделиться

4 ответа

Просто немного соответствия шаблону ...

(require '[meander.match.alpha :as pm])
(letfn [(lookup [KEY LIST]
            (pm/find LIST
                     (_ ... (~KEY ?v) . _ ...) ?v))]
    (let [LIST '(((a b) 1) (c 2) (b 3))]
        [(lookup 'b LIST)
         (lookup '(a b) LIST)
         (lookup 'd LIST)]))
=> [3 1 nil]

Это слишком много для такого простого случая, но он здесь, чтобы дать подсказку для некоторых более сложных вариантов использования.

0
ответ дан akond 19 January 2019 в 19:59
поделиться
(defn lookup [x xs]
  (first (for [[k v] xs :when (= k x)]
           v)))
0
ответ дан amalloy 19 January 2019 в 19:59
поделиться

Вот простая версия, которая работает:

(defn lookup
  [k lol]
  (let [the-map (into {}
                  (for [lst lol]
                    {(first lst) (second lst) } ))
        result (get the-map k)]
    result ) )

(lookup (quote b)      (quote (((a b) 1) (c 2) (b 3)))) => 3
(lookup (quote [a b])  (quote (((a b) 1) (c 2) (b 3)))) => 1
(lookup (quote d)      (quote (((a b) 1) (c 2) (b 3)))) => nil

Однако ваш код будет проще, если вы замените все цитируемые списки, такие как '(1 2 3), на векторы, подобные [1 2 3] (don тогда не нужно использовать начальную кавычку) и заменить все символы в кавычках, например 'a, на ключевые слова, подобные :a (также не нужно заключать в кавычки символы.

Внесение этих изменений и добавление модульных тестов выглядит следующим образом Итак:

(ns tst.demo.core
  (:use tupelo.core demo.core tupelo.test) )

(defn lookup
  [k lol]
  (get (into {} lol) k))

(dotest
  (is= 3    (lookup :b      [[[:a :b] 1] [:c 2] [:b 3]]))
  (is= 1    (lookup [:a :b] [[[:a :b] 1] [:c 2] [:b 3]]))
  (is= nil  (lookup :d      [[[:a :b] 1] [:c 2] [:b 3]])))

PS Пожалуйста, см. Brave Clojure для более подробной информации.


Обновление:

[ 1122] Нельзя использовать обычную функцию с этим синтаксисом:

(look-up b '(((a b) 1) (c 2) (b 3)))

, поскольку b является символом и подразумевается как переменная , а не как часть данных .Вы можете выбрать:

  1. Преобразовать символ b в ключевое слово :b, как я предлагал
  2. Всегда заключать в кавычки символ, например 'b (болезненный и ошибочный -prone)
  3. Написать макрос (который автоматически «заключает в кавычки» все его аргументы) и сделать так, чтобы макрос вызывал первую версию функции lookup (много работы за небольшую выгоду).

Таким образом, я предложил пункт (1) в качестве предпочтительного решения.

0
ответ дан Alan Thompson 19 January 2019 в 19:59
поделиться

Вы хотите найти первый объект в списке, который соответствует некоторым критериям (проверьте первый элемент объекта), затем Вы хотите сделать что-то к тому объекту (получите его второй элемент).

Clojure cheatsheet рекомендует some или filter для поиска seq.

  • приблизительно [1 115]
(defn lookup
  [x col]
  (some (fn [[k v]]
          (when (= x k) v))
        col))
  • фильтр
(defn lookup
  [x col]
  (->> col
       (filter (fn [[k v]]
                 (when (= x k) v)))
       first))

  • понимание списка

Также хороший вариант. См. ответ amalloy .

  • универсальное решение, если Вы хотите стать сумасшедшими

, Вы могли бы использовать любой из вышеупомянутых методов, чтобы сделать это.

(defn lookup
  [pred f col]
  (some (fn [x]
          (when (pred x)
            (f x)))
       col))

(defn lookup
  [pred f col]
  (first (for [x col :when (pred x)]
           (f x))))

;; usage: (lookup (comp '#{b} first) second data)
0
ответ дан galdre 6 April 2019 в 23:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: