在Clojure中计算GS1校验位的更多惯用方式 [英] More idiomatic way to calculate GS1 check digit in Clojure
本文介绍了在Clojure中计算GS1校验位的更多惯用方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试计算 GS1校验位,并提出了以下建议码。用于计算校验位的算法为:
I am trying to calculate a GS1 check digit and have come up with the following code. The algorithm for calculating a check digit is:
- 反转条形码
- 删除最后一位数字(计算的校验位)
- 将数字与第一,第三,第五等相加数字乘以3,偶数乘以1。
- 从等于或大于10的最接近整数倍或更高整数中减去总和
- Reverse the barcode
- Drop the last digit (calculated check digit)
- Add the digits together with first, third, fifth, e.t.c. digit multiplied by 3 and even digits multiplied by 1.
- Subtract the sum from nearest equal or higher multiple of ten
听起来很简单,但是我想出的解决方案似乎不太优雅。它确实可以工作,但是我想知道是否有一种更优雅的方式来编写它。
It sounds simple typed out but the solution I came up with seemed a bit inelegant. It does work but I want to know if there is a more elegant way of writing this.
(defn abs "(abs n) is the absolute value of n" [n]
(cond
(not (number? n)) (throw (IllegalArgumentException.
"abs requires a number"))
(neg? n) (- n)
:else n))
(defn sum-seq "adds (first number times 3) with (second number)"
[coll]
(+
(* (first coll) 3)
(second coll)))
(defn sum-digit
[s]
(reduce +
(map sum-seq
(partition 2 2 '(0)
(map #(Integer/parseInt %)
(drop 2 (clojure.string/split (clojure.string/reverse s) #"")))))))
(defn mod-higher10 "Subtracts the sum from nearest equal or higher multiple of ten"
[i]
(if (zero? (rem i 10))
0
(- 10(rem i 10))))
(defn check-digit "calculates a GS1 check digit"
[s]
(mod-higher10
(sum-digit s)))
(= (check-digit "7311518182472") 2)
(= (check-digit "7311518152284") 4)
(= (check-digit "7311518225261") 1)
(= (check-digit "7311518241452") 2)
(= (check-digit "7311518034399") 9)
(= (check-digit "7311518005955") 5)
(= (check-digit "7311518263393") 3)
(= (check-digit "7311518240943") 3)
(= (check-digit "00000012345687") 7)
(= (check-digit "012345670") 0)
推荐答案
(defn check-digit
[s]
(let [digits (map #(Integer/parseInt (str %)) s)
[chk & body] (reverse digits)
sum (apply + (map * body (cycle [3 1])))
moddiff (mod (- 10 sum) 10)]
moddiff))
此实现使用了我意识到的两个Clojure习语:
This implementation uses two clojure idioms I am conscious of:
-
let
来管理本地分解(和重用) -
map
和第二个集合,是一个无限懒惰序列,与问题相邻。
let
to manage local decomposition (and reuse)map
with a second collection, being an infinite lazy sequence 'adjacent' to the problem.
-structures列表,这样很容易将检查谓词写为(= moddiff chk)
。
Also de-structures list so that would be easy to write the checking predicate as (= moddiff chk)
.
这篇关于在Clojure中计算GS1校验位的更多惯用方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文