TXR
@(do (let ((h (hash :equal-based)))
(each ((entry '(("A" 5) ("B" 2) ("A" 12) ("B" -2) ("C" 7))))
(inc [h (first entry) 0] (second entry)))
(format t "~a\n" h)))
Run:
$ txr sumhash.txr
#H((:equal-based) ("A" 17) ("B" 0) ("C" 7))
What if we take the question literally? The question says that the input is this:
input = [["A", 5], ["B", 2], ["A", 12], ["B", -2], ["C", 7]]
and that the output looks like this:
output = {"A" => 17, "B" => 0, "C" => 7}
Fair enough. We can make a program to transform that exact input to that exact output, rather than massaging the data to fit the syntax of our programming language.
input = [@(coll :vars (key value))["@key", @{value /[+\-]?[0-9]+/}]@(last)]@(end)
@(bind (keyout valout) @(let ((h (hash :equal-based)))
(each* ((k key)
(v [mapcar (op int-str @1 10) value]))
(inc [h k 0] v))
'(,(hash-keys h) ,(hash-values h))))
@(output)
output = {@(rep)"@keyout" => @valout, @(last)"@keyout" => @valout@(end)}
@(end)
Run:
$ txr sumhash2.txr - # input read from stdin
input = [["A", 5], ["B", 2], ["A", 12], ["B", -2], ["C", 7]]
<user types Ctrl-D>
output = {"A" => 17, "B" => 0, "C" => 7}
Empty case:
$ txr sumhash2.txr -
input = []
<Ctrl-D>
output = []
Invalid input:
$ txr sumhash2.txr
foo
<Ctrl-D>
false
Word false
is output, termination status is failed.
Simplified version in which hashing is worked into data acquisition (side effects during pattern matching):
@(bind h @(hash :equal-based))
input = [@(coll)["@key", @{value /[+\-]?[0-9]+/}]@\
@(do (inc [h key 0] (int-str value 10)))@\
@(last)]@(end)
@(bind (keyout valout) (@(hash-keys h) @(hash-values h)))
@(output)
output = {@(rep)"@keyout" => @valout, @(last)"@keyout" => @valout@(end)}
@(end)
array of arrays of key|value pairs
would imply higher complexity than I think you intended. Maybe change toCreate a hash from an array of key|value pairs
? \$\endgroup\$