1 | #Region "Microsoft.VisualBasic::1c1990de5f799023cf39366e1119c940, Microsoft.VisualBasic.Core\Extensions\StringHelpers\StrUtils.vb" |
2 | |
3 | ' Author: |
4 | ' |
5 | ' asuka (amethyst.asuka@gcmodeller.org) |
6 | ' xie (genetics@smrucc.org) |
7 | ' xieguigang (xie.guigang@live.com) |
8 | ' |
9 | ' Copyright (c) 2018 GPL3 Licensed |
10 | ' |
11 | ' |
12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
13 | ' |
14 | ' |
15 | ' This program is free software: you can redistribute it and/or modify |
16 | ' it under the terms of the GNU General Public License as published by |
17 | ' the Free Software Foundation, either version 3 of the License, or |
18 | ' (at your option) any later version. |
19 | ' |
20 | ' This program is distributed in the hope that it will be useful, |
21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | ' GNU General Public License for more details. |
24 | ' |
25 | ' You should have received a copy of the GNU General Public License |
26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | |
28 | |
29 | |
30 | ' /********************************************************************************/ |
31 | |
32 | ' Summaries: |
33 | |
34 | ' Module StrUtils |
35 | ' |
36 | ' Properties: InvariantCulture |
37 | ' |
38 | ' Function: AddWithDelim, CharCode, CharCodes, CharString, (+6 Overloads) ContactWithDelim |
39 | ' ContactWithDelimSkipEmpty, ContactWithDelimSkipNull, ContactWithDelimSkipSome, CountWordFrequency, (+2 Overloads) EndsWith |
40 | ' EscapeQuotesAndBackslashes, GetCompareType, GetHeader, GetLastSubStringBetween, GetString |
41 | ' GetSubStringBetween, GetWords, LongestTag, LowerCaseFirstChar, RandomASCII |
42 | ' RandomASCIIString, RandomCharString, Remove, SplitIntoLines, SplitRemoveEmptyEntries |
43 | ' SplitWithSeparator, SplitWithSeparatorFromRight, SplitWithSpaces, (+2 Overloads) StartsWith, StartWithUpperCase |
44 | ' UpperCaseFirstChar |
45 | ' |
46 | ' /********************************************************************************/ |
47 | |
48 | #End Region |
49 | |
50 | ' |
51 | ' System.Web.Util.StrUtils |
52 | ' |
53 | ' Author(s): |
54 | ' Gonzalo Paniagua Javier (gonzalo@ximian.com) |
55 | ' |
56 | ' (C) 2005 Novell, Inc, (http://www.novell.com) |
57 | ' |
58 | |
59 | ' |
60 | ' Permission is hereby granted, free of charge, to any person obtaining |
61 | ' a copy of this software and associated documentation files (the |
62 | ' "Software"), to deal in the Software without restriction, including |
63 | ' without limitation the rights to use, copy, modify, merge, publish, |
64 | ' distribute, sublicense, and/or sell copies of the Software, and to |
65 | ' permit persons to whom the Software is furnished to do so, subject to |
66 | ' the following conditions: |
67 | ' |
68 | ' The above copyright notice and this permission notice shall be |
69 | ' included in all copies or substantial portions of the Software. |
70 | ' |
71 | ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
72 | ' EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
73 | ' MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
74 | ' NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
75 | ' LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
76 | ' OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
77 | ' WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
78 | ' |
79 | |
80 | Imports System.Globalization |
81 | Imports System.Numerics |
82 | Imports System.Runtime.CompilerServices |
83 | Imports System.Text |
84 | Imports System.Text.RegularExpressions |
85 | Imports Microsoft.VisualBasic.Language |
86 | Imports Microsoft.VisualBasic.Language.Default |
87 | Imports Microsoft.VisualBasic.Linq |
88 | Imports Microsoft.VisualBasic.Text |
89 | Imports r = System.Text.RegularExpressions.Regex |
90 | |
91 | Public Module StrUtils |
92 | |
93 | ' Exceptions: |
94 | ' T:System.ArgumentException: |
95 | ' A regular expression parsing error occurred. |
96 | ' |
97 | ' T:System.ArgumentNullException: |
98 | ' input, pattern, or replacement is null. |
99 | ' |
100 | ' T:System.ArgumentOutOfRangeException: |
101 | ' options is not a valid bitwise combination of System.Text.RegularExpressions.RegexOptions |
102 | ' values. |
103 | ' |
104 | ' T:System.Text.RegularExpressions.RegexMatchTimeoutException: |
105 | ' A time-out occurred. For more information about time-outs, see the Remarks section. |
106 | ''' <summary> |
107 | ''' In a specified input string, replaces all strings that match a specified regular |
108 | ''' expression with a specified replacement string. Specified options modify the |
109 | ''' matching operation. |
110 | ''' </summary> |
111 | ''' <param name="s$">The string to search for a match.</param> |
112 | ''' <param name="pattern$">The regular expression pattern to match.</param> |
113 | ''' <param name="opts">A bitwise combination of the enumeration values that provide options for matching.</param> |
114 | ''' <returns> |
115 | ''' A new string that is identical to the input string, except that the replacement |
116 | ''' string takes the place of each matched string. If pattern is not matched in the |
117 | ''' current instance, the method returns the current instance unchanged. |
118 | ''' </returns> |
119 | ''' |
120 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
121 | <Extension> |
122 | Public Function Remove(s$, pattern$, Optional opts As RegexOptions = RegexICSng) As String |
123 | Return r.Replace(s, pattern, "", opts) |
124 | End Function |
125 | |
126 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
127 | <Extension> |
128 | Public Function GetCompareType(type As CompareMethod) As StringComparison |
129 | If type = CompareMethod.Binary Then |
130 | Return StringComparison.Ordinal |
131 | Else |
132 | Return StringComparison.OrdinalIgnoreCase |
133 | End If |
134 | End Function |
135 | |
136 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
137 | <Extension> |
138 | Public Function GetString(bytes As IEnumerable(Of Byte), Optional encoding As Encodings = Encodings.UTF8) As String |
139 | Return encoding.CodePage.GetString(bytes.ToArray) |
140 | End Function |
141 | |
142 | ''' <summary> |
143 | ''' 从第一个字符开始,比较出最长的label串,注意,这个不是LCS问题 |
144 | ''' </summary> |
145 | ''' <param name="labels$"></param> |
146 | ''' <returns></returns> |
147 | <Extension> Public Function LongestTag(labels$()) As String |
148 | Dim l As New List(Of Char) |
149 | Dim minl% = Aggregate s In labels Into Min(s.Length) |
150 | |
151 | For i As Integer = 0 To minl |
152 | Dim index = i |
153 | Dim cs = labels.Select(Function(s) s.Chars(index)).ToArray |
154 | Dim c = cs.First |
155 | |
156 | If cs.All(Function(x) x = c) Then |
157 | l += c |
158 | Else |
159 | ' 已经有不一样的了,到终点了 |
160 | Exit For |
161 | End If |
162 | Next |
163 | |
164 | Return New String(l) |
165 | End Function |
166 | |
167 | ''' <summary> |
168 | ''' <see cref="AscW"/> |
169 | ''' </summary> |
170 | ''' <param name="s"></param> |
171 | ''' <returns></returns> |
172 | <Extension> |
173 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
174 | Public Function CharCodes(s As IEnumerable(Of Char)) As Integer() |
175 | Return s.SafeQuery.Select(AddressOf AscW).ToArray |
176 | End Function |
177 | |
178 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
179 | <Extension> |
180 | Public Function CharCode(c As Char) As Integer |
181 | Return AscW(c) |
182 | End Function |
183 | |
184 | ReadOnly newRandom As New DefaultValue(Of Random)(Function() New Random) |
185 | |
186 | ''' <summary> |
187 | ''' 32-126 |
188 | ''' </summary> |
189 | ''' <param name="len%"></param> |
190 | ''' <returns></returns> |
191 | Public Function RandomASCIIString(len%, Optional skipSymbols As Boolean = False, Optional seed As Random = Nothing) As String |
192 | With seed Or newRandom |
193 | Return CharString(len, Function() .RandomASCII(skipSymbols)) |
194 | End With |
195 | End Function |
196 | |
197 | <Extension> |
198 | Public Function RandomASCII(random As Random, skipSymbols As Boolean) As Char |
199 | With random |
200 | If Not skipSymbols Then |
201 | Return Chr(.Next(32, 127)) |
202 | Else |
203 | ' 只有字母和数字 |
204 | Select Case .NextDouble |
205 | Case <= 0.3 |
206 | ' 数字 |
207 | Return Chr(.Next(48, 58)) |
208 | Case <= 0.6 |
209 | ' 小写字母 |
210 | Return Chr(.Next(97, 123)) |
211 | Case Else |
212 | ' 大写字母 |
213 | Return Chr(.Next(65, 91)) |
214 | End Select |
215 | End If |
216 | End With |
217 | End Function |
218 | |
219 | <Extension> |
220 | Public Function RandomCharString(chars As IEnumerable(Of Char), len%) As String |
221 | With New Random |
222 | Dim buffer = chars.ToArray |
223 | Return CharString(len, Function() .Next(buffer)) |
224 | End With |
225 | End Function |
226 | |
227 | Public Function CharString(len%, getChar As Func(Of Char)) As String |
228 | Dim s As New List(Of Char) |
229 | |
230 | For i As Integer = 0 To len - 1 |
231 | s.Add(getChar()) |
232 | Next |
233 | |
234 | Return New String(s.ToArray) |
235 | End Function |
236 | |
237 | ''' <summary> |
238 | ''' <see cref="CultureInfo.InvariantCulture"/>, Gets the System.Globalization.CultureInfo object that is culture-independent |
239 | ''' (invariant). |
240 | ''' </summary> |
241 | ''' <returns></returns> |
242 | Public ReadOnly Property InvariantCulture As CultureInfo = CultureInfo.InvariantCulture |
243 | |
244 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
245 | Public Function StartsWith(str1 As String, str2 As String) As Boolean |
246 | Return StartsWith(str1, str2, False) |
247 | End Function |
248 | |
249 | Public Function StartsWith(str1 As String, str2 As String, ignore_case As Boolean) As Boolean |
250 | Dim l2 As Integer = str2.Length |
251 | If l2 = 0 Then |
252 | Return True |
253 | End If |
254 | |
255 | Dim l1 As Integer = str1.Length |
256 | If l2 > l1 Then |
257 | Return False |
258 | End If |
259 | |
260 | Return (0 = String.Compare(str1, 0, str2, 0, l2, ignore_case, StrUtils.InvariantCulture)) |
261 | End Function |
262 | |
263 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
264 | Public Function EndsWith(str1 As String, str2 As String) As Boolean |
265 | Return EndsWith(str1, str2, False) |
266 | End Function |
267 | |
268 | Public Function EndsWith(str1 As String, str2 As String, ignore_case As Boolean) As Boolean |
269 | Dim l2 As Integer = str2.Length |
270 | If l2 = 0 Then |
271 | Return True |
272 | End If |
273 | |
274 | Dim l1 As Integer = str1.Length |
275 | If l2 > l1 Then |
276 | Return False |
277 | End If |
278 | |
279 | Return (0 = String.Compare(str1, l1 - l2, str2, 0, l2, ignore_case, StrUtils.InvariantCulture)) |
280 | End Function |
281 | |
282 | Public Function EscapeQuotesAndBackslashes(attributeValue As String) As String |
283 | Dim sb As StringBuilder = Nothing |
284 | For i As Integer = 0 To attributeValue.Length - 1 |
285 | Dim ch As Char = attributeValue(i) |
286 | If ch = "'"c OrElse ch = """"c OrElse ch = "\"c Then |
287 | If sb Is Nothing Then |
288 | sb = New StringBuilder() |
289 | sb.Append(attributeValue.Substring(0, i)) |
290 | End If |
291 | sb.Append("\"c) |
292 | sb.Append(ch) |
293 | Else |
294 | If sb IsNot Nothing Then |
295 | sb.Append(ch) |
296 | End If |
297 | End If |
298 | Next |
299 | If sb IsNot Nothing Then |
300 | Return sb.ToString() |
301 | End If |
302 | Return attributeValue |
303 | End Function |
304 | |
305 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
306 | Public Function SplitRemoveEmptyEntries(value As String, separator As Char()) As String() |
307 | Return value.Split(separator, StringSplitOptions.RemoveEmptyEntries) |
308 | End Function |
309 | |
310 | ''' <summary> |
311 | ''' Split text with a separator char |
312 | ''' </summary> |
313 | ''' <param name="text">The text.</param> |
314 | ''' <param name="sep">The separator.</param> |
315 | ''' <returns></returns> |
316 | Public Function SplitWithSeparator(text As String, sep As Char) As String() |
317 | If String.IsNullOrEmpty(text) Then |
318 | Return Nothing |
319 | End If |
320 | |
321 | Dim items As String() = New String(1) {} |
322 | Dim index As Integer = text.IndexOf(sep) |
323 | |
324 | If index >= 0 Then |
325 | items(0) = text.Substring(0, index) |
326 | items(1) = text.Substring(index + 1) |
327 | Else |
328 | items(0) = text |
329 | items(1) = Nothing |
330 | End If |
331 | |
332 | Return items |
333 | End Function |
334 | |
335 | ''' <summary> |
336 | ''' Split text with a separator char |
337 | ''' </summary> |
338 | ''' <param name="text">The text.</param> |
339 | ''' <param name="sep">The separator.</param> |
340 | ''' <returns></returns> |
341 | Public Function SplitWithSeparatorFromRight(text As String, sep As Char) As String() |
342 | If String.IsNullOrEmpty(text) Then |
343 | Return Nothing |
344 | End If |
345 | |
346 | Dim items As String() = New String(1) {} |
347 | |
348 | Dim index As Integer = text.LastIndexOf(sep) |
349 | If index >= 0 Then |
350 | items(0) = text.Substring(0, index) |
351 | items(1) = text.Substring(index + 1) |
352 | Else |
353 | items(0) = text |
354 | items(1) = Nothing |
355 | End If |
356 | |
357 | Return items |
358 | End Function |
359 | |
360 | ''' <summary> |
361 | ''' Splits the text with spaces. |
362 | ''' </summary> |
363 | ''' <param name="text">The text.</param> |
364 | ''' <returns></returns> |
365 | Public Function SplitWithSpaces(text As String) As String() |
366 | Dim pattern As String = "[^ ]+" |
367 | Dim rgx As New Regex(pattern) |
368 | Dim mc As MatchCollection = rgx.Matches(text) |
369 | Dim items As String() = New String(mc.Count - 1) {} |
370 | For i As Integer = 0 To items.Length - 1 |
371 | items(i) = mc(i).Value |
372 | Next |
373 | Return items |
374 | End Function |
375 | |
376 | ''' <summary> |
377 | ''' Splits the text into lines. |
378 | ''' </summary> |
379 | ''' <param name="text">The text.</param> |
380 | ''' <returns></returns> |
381 | Public Function SplitIntoLines(text As String) As String() |
382 | Dim lines As New List(Of String)() |
383 | Dim line As New StringBuilder() |
384 | For Each ch As Char In text |
385 | Select Case ch |
386 | Case ControlChars.Cr |
387 | |
388 | Case ControlChars.Lf |
389 | lines.Add(line.ToString()) |
390 | line.Length = 0 |
391 | |
392 | Case Else |
393 | line.Append(ch) |
394 | |
395 | End Select |
396 | Next |
397 | If line.Length > 0 Then |
398 | lines.Add(line.ToString()) |
399 | End If |
400 | Return lines.ToArray() |
401 | End Function |
402 | |
403 | ''' <summary> |
404 | ''' Concats two strings with a delimiter. |
405 | ''' </summary> |
406 | ''' <param name="s1">string 1</param> |
407 | ''' <param name="delim">delimiter</param> |
408 | ''' <param name="s2">string 2</param> |
409 | ''' <returns></returns> |
410 | Public Function AddWithDelim(s1 As String, delim As String, s2 As String) As String |
411 | If String.IsNullOrEmpty(s1) Then |
412 | Return s2 |
413 | Else |
414 | Return s1 & delim & s2 |
415 | End If |
416 | End Function |
417 | ''' <summary> |
418 | ''' Contacts the with delim. |
419 | ''' </summary> |
420 | ''' <param name="str1">The STR1.</param> |
421 | ''' <param name="delim">The delim.</param> |
422 | ''' <param name="str2">The STR2.</param> |
423 | ''' <returns></returns> |
424 | Public Function ContactWithDelim(str1 As String, delim As String, str2 As String) As String |
425 | If String.IsNullOrEmpty(str1) Then |
426 | Return str2 |
427 | ElseIf String.IsNullOrEmpty(str2) Then |
428 | Return str1 |
429 | Else |
430 | Return str1 & delim & str2 |
431 | End If |
432 | End Function |
433 | |
434 | ''' <summary> |
435 | ''' Contact with delim, delim is used after the first not Empty item |
436 | ''' </summary> |
437 | ''' <param name="items"></param> |
438 | ''' <param name="delim"></param> |
439 | ''' <returns></returns> |
440 | Public Function ContactWithDelimSkipEmpty(items As IEnumerable(Of String), delim As String) As String |
441 | Return ContactWithDelimSkipSome(items, delim, String.Empty) |
442 | End Function |
443 | |
444 | ''' <summary> |
445 | ''' Contact with delim, delim is used after the first not null item |
446 | ''' </summary> |
447 | ''' <param name="items"></param> |
448 | ''' <param name="delim"></param> |
449 | ''' <returns></returns> |
450 | Public Function ContactWithDelimSkipNull(items As IEnumerable(Of String), delim As String) As String |
451 | Return ContactWithDelimSkipSome(items, delim, Nothing) |
452 | End Function |
453 | |
454 | ''' <summary> |
455 | ''' Contacts the items with delim skip some. |
456 | ''' </summary> |
457 | ''' <param name="items">The items.</param> |
458 | ''' <param name="delim">The delim.</param> |
459 | ''' <param name="skip">The skip.</param> |
460 | ''' <returns></returns> |
461 | Public Function ContactWithDelimSkipSome(items As IEnumerable(Of String), delim As String, skip As String) As String |
462 | Dim text As New StringBuilder() |
463 | Dim isFirst As Boolean = True |
464 | For Each item As String In items |
465 | If item = skip Then |
466 | Continue For |
467 | End If |
468 | If isFirst Then |
469 | isFirst = False |
470 | Else |
471 | text.Append(delim) |
472 | End If |
473 | text.Append(item) |
474 | Next |
475 | Return text.ToString() |
476 | End Function |
477 | |
478 | ''' <summary> |
479 | ''' Contacts the items with delim. |
480 | ''' </summary> |
481 | ''' <param name="items">The items.</param> |
482 | ''' <param name="delim">The delim.</param> |
483 | ''' <returns></returns> |
484 | Public Function ContactWithDelim(items As IEnumerable(Of String), delim As String) As String |
485 | Return ContactWithDelim(items, delim, Nothing, Nothing) |
486 | End Function |
487 | ''' <summary> |
488 | ''' Contacts the items with delim. |
489 | ''' </summary> |
490 | ''' <param name="items">The items.</param> |
491 | ''' <param name="delim">The delim.</param> |
492 | ''' <param name="initialValue">The initial value.</param> |
493 | ''' <returns></returns> |
494 | Public Function ContactWithDelim(items As IEnumerable(Of String), delim As String, initialValue As String) As String |
495 | Return ContactWithDelim(items, delim, initialValue, Nothing) |
496 | End Function |
497 | ''' <summary> |
498 | ''' Contacts the items with delim. |
499 | ''' </summary> |
500 | ''' <param name="items">The items.</param> |
501 | ''' <param name="delim">The delim.</param> |
502 | ''' <param name="initialValue">The initial value.</param> |
503 | ''' <param name="endValue">The end value.</param> |
504 | ''' <returns></returns> |
505 | Public Function ContactWithDelim(items As IEnumerable(Of String), delim As String, initialValue As String, endValue As String) As String |
506 | Dim text As New StringBuilder(initialValue) |
507 | Dim isFirst As Boolean = True |
508 | For Each item As String In items |
509 | If isFirst Then |
510 | isFirst = False |
511 | Else |
512 | text.Append(delim) |
513 | End If |
514 | text.Append(item) |
515 | Next |
516 | text.Append(endValue) |
517 | Return text.ToString() |
518 | End Function |
519 | |
520 | ''' <summary> |
521 | ''' Contacts the items with delim. |
522 | ''' </summary> |
523 | ''' <typeparam name="T"></typeparam> |
524 | ''' <param name="items">The items.</param> |
525 | ''' <param name="delim">The delim.</param> |
526 | ''' <returns></returns> |
527 | Public Function ContactWithDelim(Of T)(items As IEnumerable(Of T), delim As String) As String |
528 | Return ContactWithDelim(Of T)(items, delim, Nothing, Nothing) |
529 | End Function |
530 | |
531 | ''' <summary> |
532 | ''' Contacts the items with delim. |
533 | ''' </summary> |
534 | ''' <typeparam name="T"></typeparam> |
535 | ''' <param name="items">The items.</param> |
536 | ''' <param name="delim">The delim.</param> |
537 | ''' <param name="initialValue">The initial value.</param> |
538 | ''' <param name="endValue">The end value.</param> |
539 | ''' <returns></returns> |
540 | Public Function ContactWithDelim(Of T)(items As IEnumerable(Of T), delim As String, initialValue As String, endValue As String) As String |
541 | Dim text As New StringBuilder() |
542 | text.Append(initialValue) |
543 | Dim isFirst As Boolean = True |
544 | For Each item As T In items |
545 | If isFirst Then |
546 | isFirst = False |
547 | Else |
548 | text.Append(delim) |
549 | End If |
550 | text.Append(item.ToString()) |
551 | Next |
552 | text.Append(endValue) |
553 | Return text.ToString() |
554 | End Function |
555 | |
556 | ''' <summary> |
557 | ''' Gets the header. |
558 | ''' </summary> |
559 | ''' <param name="text">The text.</param> |
560 | ''' <param name="length">The length.</param> |
561 | ''' <returns></returns> |
562 | Public Function GetHeader(text As String, length As Integer) As String |
563 | If text.Length <= length Then |
564 | Return text |
565 | Else |
566 | Return text.Substring(0, length) |
567 | End If |
568 | End Function |
569 | |
570 | ''' <summary> |
571 | ''' Get the sub string between 'ket' and 'bra'. |
572 | ''' </summary> |
573 | ''' <param name="text"></param> |
574 | ''' <param name="bra"></param> |
575 | ''' <param name="ket"></param> |
576 | ''' <returns></returns> |
577 | Public Function GetSubStringBetween(text As String, bra As Char, ket As Char) As String |
578 | If text Is Nothing Then |
579 | Return Nothing |
580 | End If |
581 | Dim braIndex As Integer = text.IndexOf(bra) |
582 | If braIndex > -1 Then |
583 | Dim ketIndex As Integer = text.IndexOf(ket) |
584 | If ketIndex > braIndex Then |
585 | Return text.Substring(braIndex + 1, ketIndex - braIndex - 1) |
586 | End If |
587 | End If |
588 | Return String.Empty |
589 | End Function |
590 | |
591 | ''' <summary> |
592 | ''' Get the sub string between 'ket' and 'bra'. |
593 | ''' </summary> |
594 | ''' <param name="text"></param> |
595 | ''' <param name="bra"></param> |
596 | ''' <param name="ket"></param> |
597 | ''' <returns></returns> |
598 | Public Function GetLastSubStringBetween(text As String, bra As Char, ket As Char) As String |
599 | If text Is Nothing Then |
600 | Return Nothing |
601 | End If |
602 | Dim braIndex As Integer = text.LastIndexOf(bra) |
603 | If braIndex > -1 Then |
604 | Dim ketIndex As Integer = text.LastIndexOf(ket) |
605 | If ketIndex > braIndex Then |
606 | Return text.Substring(braIndex + 1, ketIndex - braIndex - 1) |
607 | End If |
608 | End If |
609 | Return String.Empty |
610 | End Function |
611 | |
612 | ''' <summary> |
613 | ''' Starts with upper case. |
614 | ''' </summary> |
615 | ''' <param name="name">The name.</param> |
616 | ''' <returns></returns> |
617 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
618 | <Extension> |
619 | Public Function StartWithUpperCase(name As String) As Boolean |
620 | Return name.Length >= 1 AndAlso Char.IsUpper(name(0)) |
621 | End Function |
622 | |
623 | ''' <summary> |
624 | ''' Uppers the case of the first char. |
625 | ''' </summary> |
626 | ''' <param name="name">The name.</param> |
627 | ''' <returns></returns> |
628 | <Extension> |
629 | Public Function UpperCaseFirstChar(name As String) As String |
630 | If name?.Length > 0 AndAlso Char.IsLower(name(0)) Then |
631 | Dim chars As Char() = name.ToCharArray() |
632 | chars(0) = [Char].ToUpper(chars(0)) |
633 | Return New String(chars) |
634 | Else |
635 | Return name |
636 | End If |
637 | End Function |
638 | |
639 | ''' <summary> |
640 | ''' Lowers the case of the first char. |
641 | ''' </summary> |
642 | ''' <param name="name">The name.</param> |
643 | ''' <returns></returns> |
644 | Public Function LowerCaseFirstChar(name As String) As String |
645 | If name.Length >= 1 AndAlso Char.IsUpper(name(0)) Then |
646 | Dim chars As Char() = name.ToCharArray() |
647 | chars(0) = [Char].ToLower(chars(0)) |
648 | Return New String(chars) |
649 | End If |
650 | Return name |
651 | End Function |
652 | |
653 | ''' <summary> |
654 | ''' split text into words by space and newline chars, multiple spaces are treated as a single space. |
655 | ''' </summary> |
656 | ''' <param name="text"></param> |
657 | ''' <returns></returns> |
658 | Public Function GetWords(text As String) As String() |
659 | Dim tokens As New List(Of String)() |
660 | Dim token As New List(Of Char)() |
661 | |
662 | For Each ch As Char In text |
663 | Select Case ch |
664 | Case " "c, ControlChars.Cr, ControlChars.Lf |
665 | If token.Count > 0 Then |
666 | tokens.Add(New String(token.ToArray())) |
667 | token.Clear() |
668 | End If |
669 | Case Else |
670 | token.Add(ch) |
671 | End Select |
672 | Next |
673 | |
674 | If token.Count > 0 Then |
675 | tokens.Add(New String(token.ToArray())) |
676 | End If |
677 | |
678 | Return tokens.ToArray() |
679 | End Function |
680 | |
681 | Public Function CountWordFrequency(article As String, delimiters As String) As Dictionary(Of String, Integer) |
682 | If article Is Nothing Then |
683 | Throw New ArgumentNullException("article") |
684 | End If |
685 | If delimiters Is Nothing Then |
686 | Throw New ArgumentNullException("delimiters") |
687 | End If |
688 | Dim words As New List(Of String)() |
689 | Dim buffer As New List(Of Char)() |
690 | For Each c As Char In article |
691 | If delimiters.IndexOf(c) = -1 Then |
692 | buffer.Add(c) |
693 | Else |
694 | If buffer.Count > 0 Then |
695 | words.Add(New String(buffer.ToArray())) |
696 | buffer.Clear() |
697 | End If |
698 | End If |
699 | Next |
700 | If buffer.Count > 0 Then |
701 | words.Add(New String(buffer.ToArray())) |
702 | End If |
703 | |
704 | Dim table As New Dictionary(Of String, Integer)() |
705 | For Each word As String In words |
706 | If table.ContainsKey(word) Then |
707 | table(word) += 1 |
708 | Else |
709 | table.Add(word, 1) |
710 | End If |
711 | Next |
712 | Return table |
713 | End Function |
714 | End Module |