Class: String
- Defined in:
- lib/sequence_logo/ytilib/addon.rb,
lib/sequence_logo/ytilib/addon.rb
Overview
String.class_eval do
def to_id
return self.gsub(/[^.\w]/, '_')
end
end
Direct Known Subclasses
Instance Method Summary collapse
- #compl ⇒ Object (also: #comp, #complement)
- #compl! ⇒ Object (also: #comp!, #complement!)
-
#prev(collapse = false) ⇒ Object
(also: #pred)
The opposite of String::next / String::succ.
-
#prev! ⇒ Object
(also: #pred!)
As (extended) String::pred / String::prev, but modifies the string in place rather than returning a copy.
- #revcomp ⇒ Object
- #revcomp! ⇒ Object
- #to_id ⇒ Object
Instance Method Details
#compl ⇒ Object Also known as: comp, complement
65 66 67 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 65 def compl return self.tr("acgtACGT", "tgcaTGCA") end |
#compl! ⇒ Object Also known as: comp!, complement!
60 61 62 63 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 60 def compl! self.tr!("acgtACGT", "tgcaTGCA") return self end |
#prev(collapse = false) ⇒ Object Also known as: pred
The opposite of String::next / String::succ. It is impossible to be a complete opposite because both “9”.next = “10” and “09”.next = “10”; if going backwards from “10” there’s no way to know whether the result should be “09” or “9”. Where the first ranged character is about to underflow and the next character is within the same range the result is shrunk down - that is, “10” goes to “9”, “aa” goes to “z”; any non- range prefix or suffix is OK, e.g. “+!$%10-=+” goes to “+!$%9-=+”. Items in the middle of a string don’t do this - e.g. “12.10” goes to “12.09”, to match how “next” would work as best as possible.
The standard “next” function works on strings that contain no alphanumeric characters, using character codes. This implementation of “prev” does not work on such strings - while strings may contain any characters you like, only the alphanumeric components are operated upon.
Should total underflow result, “nil” will be returned - e.g. “00”.prev returns ‘nil’, as does “a”.prev. This is done even if there are other characters in the string that were not touched - e.g. “+0.0”.prev also returns “nil”. Broadly speaking, a “nil” return value is used for any attempt to find the previous value of a string that could not have been generated using “next” in the first place.
As with “next” sometimes the result of “prev” can be a little obscure so it is often best to try out things using “irb” if unsure. Note in particular that software revision numbers do not necessarily behave predictably, because they don’t with “next”! E.g. “12.4.9” might go to “12.4.10” for a revision number, but “12.4.9”.next = “12.5.0”. Thus “12.5.0”.prev = “12.4.9” and “12.4.10”.prev = “12.4.09” (because the only way to make “12.4.10” using “next” is to start at “12.4.09”).
Since ‘succ’ (successor) is an alias for ‘next’, so ‘pred’ (predecessor) is an alias for ‘prev’.
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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 132 def prev(collapse = false) str = self.dup early_exit = false any_done = false ranges = [ ('0'[0]..'9'[0]), ('a'[0]..'z'[0]), ('A'[0]..'Z'[0]), nil ] # Search forward for the first in-range character. If found check # to see if that character is "1", "a" or "A". If it is, record # its index (from 0 to string length - 1). We'll need this if # underflows wrap as far as the found byte because in that case # this first found byte should be deleted ("aa..." -> "z...", # "10..." -> "9..."). first_ranged = nil for index in (1..str.length) byte = str[index - 1] # Determine whether or not the current byte is a number, lower case # or upper case letter. We expect 'select' to only find one matching # array entry in 'ranges', thus we dereference index 0 after the # 'end' to put a matching range from within 'ranges' into 'within', # or 'nil' for any unmatched byte. within = ranges.select do |range| range.nil? or range.include?(byte) end [0] unless within.nil? case within.first when '0'[0] match_byte = '1'[0] else match_byte = within.first end first_ranged = index - 1 if (byte == match_byte) first_within = within break end end for index in (1..str.length) # Process the input string in reverse character order - fetch the # bytes via negative index. byte = str[-index] within = ranges.select do |range| range.nil? or range.include?(byte) end [0] # Skip this letter unless within a known range. Otherwise note that # at least one byte was able to be processed. next if within.nil? any_done = true # Decrement the current byte. If it is still within its range, set # the byte and bail out - we're finished. Flag the early exit. If # the byte is no longer within range, wrap the character around # and continue the loop to carry the decrement to an earlier byte. byte = byte - 1 if (within.include? byte) str[-index] = byte early_exit = true break else str[-index] = within.last # If we've just wrapped around a character immediately after the # one found right at the start ('0', 'a' or 'A') then this first # ranged character should be deleted (so "10" -> "09" if (first_ranged != nil and first_within.include?(byte + 1) and (first_ranged - str.length) == -(index + 1)) str.slice!(-(index + 1)) early_exit = true break end end end # From outer 'for' loop # If we did process at least one byte but we did not exit early, then # the loop completed due to carrying a decrement to other bytes. This # means an underflow condition - return 'nil'. if (any_done == true and early_exit == false) return nil else return str end end |
#prev! ⇒ Object Also known as: pred!
As (extended) String::pred / String::prev, but modifies the string in place rather than returning a copy. If underflow occurs, the string will be unchanged. Returns ‘self’.
238 239 240 241 242 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 238 def prev! new_str = prev self.replace(new_str) unless new_str.nil? return self end |
#revcomp ⇒ Object
74 75 76 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 74 def revcomp return comp.reverse end |
#revcomp! ⇒ Object
78 79 80 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 78 def revcomp! return comp!.reverse! end |
#to_id ⇒ Object
82 83 84 |
# File 'lib/sequence_logo/ytilib/addon.rb', line 82 def to_id return self.gsub(/[^.\w]/, '_').upcase end |