-
Notifications
You must be signed in to change notification settings - Fork 0
/
trimming.html
159 lines (136 loc) · 12.5 KB
/
trimming.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<!DOCTYPE html PUBLIC ""
"">
<html><head><meta charset="UTF-8" /><title>Trimming</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script><link rel="stylesheet" type="text/css" href="css/randomseed.css" /></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Smangler</span> <span class="project-version">1.0.4</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="splitting.html"><div class="inner"><span>Splitting</span></div></a></li><li class="depth-1 current"><a href="trimming.html"><div class="inner"><span>Trimming</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>smangler</span></div></div></li><li class="depth-2 branch"><a href="smangler.api.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>api</span></div></a></li><li class="depth-2"><a href="smangler.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#trimming" id="trimming"></a>Trimming</h1>
<p>Basic string trimming is handled by the API function <a href="smangler.api.html#var-trim-both"><code>trim-both</code></a> from the namespace <a href="smangler.api.html"><code>smangler.api</code></a>. In its single-argument version it trims a given string on both ends if the characters are the same. It repeats this operation until there is nothing to trim.</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both "abba") ; => ""
(sa/trim-both "some") ; => "some"
(sa/trim-both "barkrab") ; => "k"
</code></pre>
<h2><a href="#coercion-to-strings" id="coercion-to-strings"></a>Coercion to strings</h2>
<p>You can pass other types of arguments and they will be coerced to strings. Single characters and numbers are supported, and so are collections of strings, characters and numbers:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both 1111) ; => ""
(sa/trim-both 12345) ; => "12345"
(sa/trim-both 12021) ; => "0"
(sa/trim-both \a) ; => "a"
(sa/trim-both [1 0 1]) ; => "0"
(sa/trim-both [\a \b \a]) ; => "b"
(sa/trim-both ["abc" "ba"]) ; => "c"
</code></pre>
<h2><a href="#custom-matcher" id="custom-matcher"></a>Custom matcher</h2>
<p>Optionally, you can call <code>trim-both</code> with 2 arguments passed. In this scenario the first argument should be a function which takes a single character and returns either some character, <code>nil</code> or <code>false</code>. This function, called the matcher, is used on the first character of a string to determine whether it should be removed (along with the last character):</p>
<pre><code class="language-clojure">(fn [character]
(and (some-lookup character) ; some-lookup checks if a character should be trimmed
character)) ; important to return the character, nil or false
</code></pre>
<p>If the matcher returns <code>nil</code> or <code>false</code> then no trimming occurs. If the matcher returns a character it is compared by <code>trim-both</code> with the right-most character of the trimmed string and if they’re equal then trimming is performed.</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
;; Only 'a' will be trimmed since the matcher
;; checks if it is this letter.
(sa/trim-both #(and (= \a %) %) "abxba") ; => "bxb"
;; Beginning 'a' and ending 'z' will be trimmed
;; because matcher requires that 'a' must have corresponding 'z'.
(sa/trim-both #(and (= \a %) \z) "abcdz") ; => "bcd"
</code></pre>
<h3><a href="#sets-as-matchers" id="sets-as-matchers"></a>Sets as matchers</h3>
<p>It is common to use sets for matching the same characters on both ends. This is possible because in Clojure sets implement function interface which allows us to perform quick lookup:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both #{\a \b} "abxba") ; => "x"
(sa/trim-both #{\a} "abxba") ; => "bxb"
</code></pre>
<h3><a href="#maps-as-matchers" id="maps-as-matchers"></a>Maps as matchers</h3>
<p>Due to the characteristics of a matching function it is possible to use maps as since they also implement function interface. That will allow us to match both ends of a string in an easy way:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both {\a \a} "abxba") ; => "bxb"
(sa/trim-both {\a \z} "abcdz") ; => "bcd"
</code></pre>
<h3><a href="#coercion-to-matcher" id="coercion-to-matcher"></a>Coercion to matcher</h3>
<p>You can pass other types of arguments and they will be coerced to matchers. Single characters, strings and numbers are supported, and so are collections of strings, characters and numbers:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both \a "abxba") ; => "bxb"
(sa/trim-both 1 "1abc1") ; => "abc"
(sa/trim-both 12 "21abc12") ; => "abc"
(sa/trim-both [1 2] "21abc12") ; => "abc"
(sa/trim-both [\a \b] "abxba") ; => "x"
(sa/trim-both "ab" "abxba") ; => "x"
</code></pre>
<h2><a href="#two-characters-and-astring" id="two-characters-and-astring"></a>Two characters and a string</h2>
<p>In its 3-argument version the function simply takes 2 characters and a string. The given characters must match first and last characters of the string for trimming to be performed:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both \a \a "abxba") ; => "bxb"
(sa/trim-both \a \a "aaxaa") ; => "x"
(sa/trim-both \1 \1 "1abc1") ; => "abc"
(sa/trim-both \a \z "axz") ; => "x"
(sa/trim-both \a \z "aaxzz") ; => "x"
</code></pre>
<h2><a href="#trimming-once" id="trimming-once"></a>Trimming once</h2>
<p>If you want to perform trimming just once, use <a href="smangler.api.html#var-trim-both-once"><code>trim-both-once</code></a> API function. It works the same way as <code>trim-both</code> but stops after first operation (if any):</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both-once "abba") ; => "bb"
(sa/trim-both-once "some") ; => "some"
(sa/trim-both-once "barkrab") ; => "arkra"
(sa/trim-both-once "ab" "barkrab") ; => "arkra"
(sa/trim-both-once #{\a \b} "barkrab") ; => "arkra"
(sa/trim-both-once \a \a "aaxaa") ; => "axa"
</code></pre>
<h2><a href="#trimming-once-with-preservation" id="trimming-once-with-preservation"></a>Trimming once with preservation</h2>
<p>To make certain operations easy there is <a href="smangler.api.html#var-trim-both-once-with-orig"><code>trim-both-once-with-orig</code></a> function which returns a sequence of 1 or 2 elements, the first being always the original string with the latter being its trimmed version. If there is nothing to trim, only one element will be present in the resulting sequence:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both-once-with-orig "abba") ; => ("abba", "bb")
(sa/trim-both-once-with-orig "some") ; => ("some")
(sa/trim-both-once-with-orig "barkrab") ; => ("barkrab" "arkra")
(sa/trim-both-once-with-orig "ab" "barkrab") ; => ("barkrab" "arkra")
(sa/trim-both-once-with-orig #{\a \b} "barkrab") ; => ("barkrab" "arkra")
(sa/trim-both-once-with-orig \a \a "aaxaa") ; => ("aaxaa" "axa")
</code></pre>
<h2><a href="#sequence-of-trimming-steps" id="sequence-of-trimming-steps"></a>Sequence of trimming steps</h2>
<p>If there is a need for keeping all subsequent steps of trimming you can use the function <a href="smangler.api.html#var-trim-both-seq"><code>trim-both-seq</code></a>. It works the same as <code>trim-both</code> but returns a lazy sequence of strings, each being the result of next step of iterative trimming:</p>
<pre><code class="language-clojure">(require '[smangler.api :as sa])
(sa/trim-both-seq nil) ; => nil
(sa/trim-both-seq "abba") ; => ("abba", "bb", "")
(sa/trim-both-seq "some") ; => ("some")
(sa/trim-both-seq "barkrab") ; => ("barkrab" "arkra" "rkr" "k")
(sa/trim-both-seq "ab" "barkrab") ; => ("barkrab" "arkra" "rkr")
(sa/trim-both-seq #{\a \b} "barkrab") ; => ("barkrab" "arkra" "rkr")
(sa/trim-both-seq \a \a "aaxaa") ; => ("aaxaa" "axa" "x")
</code></pre>
<h2><a href="#low-level-trimming" id="low-level-trimming"></a>Low-level trimming</h2>
<p>Certain applications may require more efficient and/or more strict trimming functions. It is particularly not recommended but there is a <a href="smangler.core.html"><code>smangler.core</code></a> namespace which contains trimming operations which are a bit faster than those in API. They require certain argument types and no coercion is performed. The returned values may also differ when it comes to handling corner cases (<code>nil</code> or empty values, not finding a match, etc.):</p>
<ul>
<li><a href="smangler.core.html#var-trim-both"><code>trim-both</code></a>,</li>
<li><a href="smangler.core.html#var-trim-both-once"><code>trim-both-once</code></a>.</li>
</ul>
<p>The function <a href="smangler.core.html#var-trim-both"><code>trim-both</code></a> from the namespace <a href="smangler.core.html"><code>smangler.core</code></a> takes a string as its last (or only) argument and trims its characters on both ends are the same:</p>
<pre><code class="language-clojure">(require '[smangler.core :as c])
(c/trim-both nil) ; => nil
(c/trim-both "abcd") ; => "abcd"
(c/trim-both "abca") ; => "bc"
(c/trim-both "aabaa") ; => "b"
</code></pre>
<p>Optionally it can also take a matching function as the first argument. The function should take a character and return a character, <code>nil</code> or <code>false</code>. If a character passed as an argument to this matcher will be the first character of the passed string and if a value returned by this match will be equal to the last character of the passed string trimming will occur:</p>
<pre><code class="language-clojure">(require '[smangler.core :as c])
(c/trim-both #{\a \b} nil) ; => nil
(c/trim-both #{\a \b} "abba") ; => ""
(c/trim-both #(and (= % \a) %) "abba") ; => "bb"
(c/trim-both {\a \z} "abbz") ; => "bb"
</code></pre>
<p>Similarly to its counterpart from <code>smangler.api</code> the function can handle 3 arguments. In this case the first two should be characters matching the beginning and the end of a string:</p>
<pre><code class="language-clojure">(require '[smangler.core :as c])
(c/trim-both \a \z nil) ; => nil
(c/trim-both \a \z "abbz") ; => "bb"
</code></pre>
<p>The function <a href="smangler.core.html#var-trim-both-once"><code>trim-both-once</code></a> from the namespace <a href="smangler.core.html"><code>smangler.core</code></a> works the same way as <code>trim-both</code> but trims the given string only once. However, it will return <code>nil</code> instead of the original string if there is nothing to trim:</p>
<pre><code class="language-clojure">(require '[smangler.core :as c])
(c/trim-both-once nil) ; => nil
(c/trim-both-once "") ; => nil
(c/trim-both-once "aa") ; => ""
(c/trim-both-once "abba") ; => "bb"
(c/trim-both-once "some") ; => nil
(c/trim-both-once "barkrab") ; => "arkra"
(c/trim-both-once (set "ab") "barkrab") ; => "arkra"
(c/trim-both-once #{\a \b} "barkrab") ; => "arkra"
(c/trim-both-once (set "abcd") "xyz") ; => nil
(c/trim-both-once \a \a "aaxaa") ; => "axa"
</code></pre>
</div></div></div></body></html>