И, как обычно, в Clojure всегда есть одна строка в reduce
, чтобы решить исходную проблему: «Я просто хочу подсчитать, сколько раз появляется di git».
(reduce (fn [m ch] (update m ch (fnil inc 0))) {} "123123123")
==> {\1 3, \2 3, \3 3}
Многое, чтобы распаковать здесь, если вы новичок в Clojure. Reduce используется для перебора строки, подсчета вхождений каждого символа и сохранения его на карте.
От внутреннего к внешнему:
(fnil inc 0)
возвращает функцию, которая запускает inc
с любой аргумент предоставлен. Однако, если аргумент равен nil, он заменит его на 0. Это идеально подходит для добавления новой записи на карту.
update
используется для поиска существующего ключа ch
в m
и вычисления нового значения (путем вызова функции, возвращаемой (fnil inc 0
)), т. Е. Если ch
не в m
будет выполняться (inc 0) => 1
, если ch
находится в m
, будет возвращаться увеличенный счетчик.
(fn [m ch] ...)
- функция уменьшения. Это самая сложная часть для понимания. Требуется два параметра. Первым является последнее возвращаемое значение этой функции (созданное на более ранней итерации) или, если это первый раз, когда эта функция запускается, предоставляется начальное значение: {}
(есть и третий способ вызова Reduce, см. (doc reduce)
)
Второй аргумент ch
является текущим символом в предоставленной строке (поскольку String является CharSequence и считается как коллекция).
Таким образом, функция сокращения вызывается для каждого символа и мы просто возвращаем текущую карту с обновленным счетчиком для каждого символа, начиная с {}
.