Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: book.asciidoc

Issue 12335109: Strings recipes for the Dart Cookbook (Closed) Base URL: https://github.com/dart-lang/cookbook.git@master
Patch Set: Made most changes requested my Kathy. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | book.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 = Dart Cookbook
2 :author: Shailen Tuli
3 :encoding: UTF-8
4
5 == Strings
6
7 === Concatenating Strings
8
9 ==== Problem
10
11 You want to concatenate strings in Dart. You tried using `+`, but that
12 resulted in an error.
13
14 ==== Solution
15
16 Use adjacent string literals:
17
18 --------------------------------------------------
19 var fact = 'Dart' 'is' ' fun!'; // 'Dart is fun!'
20 --------------------------------------------------
21
22 ==== Discussion
23
24 Adjacent literals work over multiple lines:
25
26 -------------------------
27 var fact = 'Dart'
28 'is'
29 'fun!'; // 'Dart is fun!'
30 -------------------------
31
32 They also work when using multiline strings:
33
34 ----------------------------------------
35 var lunch = '''Peanut
36 butter'''
37 '''and
38 jelly'''; // 'Peanut\nbutter and\njelly'
39 ----------------------------------------
40
41 You can concatenate adjacent single line literals with multiline
42 strings:
43
44 --------------------------------------
45 var funnyGuys = 'Dewey ' 'Cheatem'
46 ''' and
47 Howe'''; // 'Dewey Cheatem and\n Howe'
48 --------------------------------------
49
50 ===== Alternatives to adjacent string literals
51
52 You can use the `concat()` method on a string to concatenate it to
53 another string:
54
55 ---------------------------------------------------
56 var film = filmToWatch();
57 film = film.concat('\n'); // 'The Big Lebowski\n'
58 ---------------------------------------------------
59
60 Because `concat()` creates a new string every time it is invoked, a long
61 chain of `concat()` s can be expensive. Avoid those. Use a StringBuffer
62 instead (see _Incrementally building a string efficiently using a
63 StringBuffer_, below).
64
65 Use `join()` to combine a sequence of strings:
66
67 -----------------------------------------------------------------------
68 var film = ['The', 'Big', 'Lebowski']).join(' '); // 'The Big Lebowski'
69 -----------------------------------------------------------------------
70
71 You can also use string interpolation to concatenate strings (see
72 _Interpolating expressions inside strings_, below).
73
74 === Interpolating expressions inside strings
75
76 ==== Problem
77
78 You want to embed Dart code inside strings.
79
80 ==== Solution
81
82 You can put the value of an expression inside a string by using
83 $\{expression}.
84
85 ----------------------------------------------------------------------
86 var favFood = 'sushi';
87 var whatDoILove = 'I love ${favFood.toUpperCase()}'; // 'I love SUSHI'
88 ----------------------------------------------------------------------
89
90 You can skip the \{} if the expression is an identifier:
91
92 ------------------------------------------------------
93 var whatDoILove = 'I love $favFood'; // 'I love sushi'
94 ------------------------------------------------------
95
96 ==== Discussion
97
98 An interpolated string, `'string ${expression}` is equivalent to the
99 concatenation of the strings `string` and `expression.toString()`.
100 Consider this code:
101
102 -----------------------------------------------------
103 var four = 4;
104 var seasons = 'The $four seasons'; // 'The 4 seasons'
105 -----------------------------------------------------
106
107 This is functionally equivalent to the following:
108
109 -------------------------------------------------------------
110 var seasons = 'The '.concat(4.toString()).concat(' seasons');
111 // 'The 4 seasons'
112 -------------------------------------------------------------
113
114 You should consider implementing a `toString()` method for user-defined
115 objects. Here's what happens if you don't:
116
117 -------------------------------------------------------
118 class Point {
119 num x, y;
120 Point(this.x, this.y);
121 }
122
123 var point = new Point(3, 4);
124 print('Point: $point'); // "Point: Instance of 'Point'"
125 -------------------------------------------------------
126
127 Probably not what you wanted. Here is the same example with an explicit
128 `toString()`:
129
130 ----------------------------------------------
131 class Point {
132 ...
133
134 String toString() => 'x: $x, y: $y';
135 }
136
137 print('Point: $point'); // 'Point: x: 3, y: 4'
138 ----------------------------------------------
139
140 === Handling special characters within strings
141
142 ==== Problem
143
144 You want to put newlines, dollar signs, or other special characters in strings.
145
146 ==== Solution
147
148 Prefix special characters with a `\`.
149
150 ------------------------
151 print(Wile\nCoyote');
152 // Wile
153 // Coyote
154 ------------------------
155
156 ==== Discussion
157
158 Dart designates a few characters as special, and these can be escaped:
159
160 * \n for newline, equivalent to \x0A.
161 * \r for carriage return, equivalent to \x0D.
162 * \f for form feed, equivalent to \x0C.
163 * \b for backspace, equivalent to \x08.
164 * \t for tab, equivalent to \x09.
165 * \v for vertical tab, equivalent to \x0B.
166
167 If you prefer, you can use `\x` or `\u` notation to indicate the special
168 character:
169
170 -----------------------------------------------------------
171 print('Wile\x0ACoyote'); // Same as print('Wile\nCoyote')
172 print('Wile\u000ACoyote'); // Same as print('Wile\nCoyote')
173 -----------------------------------------------------------
174
175 You can also use `\u{}` notation:
176
177 -------------------------------------------------------------
178 print('Wile\u{000A}Coyote'); // same as print('Wile\nCoyote')
179 -------------------------------------------------------------
180
181 You can also escape the `$` used in string interpolation:
182
183 -------------------------------------------------------------------------
184 var superGenius = 'Wile Coyote';
185 print('$superGenius and Road Runner'); // 'Wile Coyote and Road Runner'
186 print('\$superGenius and Road Runner'); // '$superGenius and Road Runner'
187 -------------------------------------------------------------------------
188
189 If you escape a non-special character, the `\` is ignored:
190
191 -------------------------------------------
192 print('Wile \E Coyote'); // 'Wile E Coyote'
193 -------------------------------------------
194
195
196 === Incrementally building a string using a StringBuffer
197
198 ==== Problem
199
200 You want to collect string fragments and combine them in an efficient
201 manner.
202
203 ==== Solution
204
205 Use a StringBuffer to programmatically generate a string. Consider this code
206 below for assembling a series of urls from fragments:
207
208 --------------------------------------------------------------------------
209 var data = [{'scheme': 'https', 'domain': 'news.ycombinator.com'},
210 {'domain': 'www.google.com'},
211 {'domain': 'reddit.com', 'path': 'search', 'params': 'q=dart'}
212 ];
213
214 String assembleUrlsUsingStringBuffer(entries) {
215 StringBuffer sb = new StringBuffer();
216 for (final item in entries) {
217 sb.write(item['scheme'] != null ? item['scheme'] : 'http');
218 sb.write("://");
219 sb.write(item['domain']);
220 sb.write('/');
221 sb.write(item['path'] != null ? item['path'] : '');
222 if (item['params'] != null) {
223 sb.write('?');
224 sb.write(item['params']);
225 }
226 sb.write('\n');
227 }
228 return sb.toString();
229 }
230
231 // https://news.ycombinator.com/
232 // http://www.google.com/
233 // http://reddit.com/search?q=dart
234 --------------------------------------------------------------------------
235
236 A StringBuffer collects string fragments, but does not generate a new string
237 until `toString()` is called.
238
239 ==== Discussion
240
241 Using a StringBuffer is vastly more efficient than concatenating fragments
242 at each step: Consider this rewrite of the above code:
243
244 -------------------------------------------------------------------------
245 String assembleUrlsUsingConcat(entries) {
246 var urls = '';
247 for (final item in entries) {
248 urls = urls.concat(item['scheme'] != null ? item['scheme'] : 'http');
249 urls = urls.concat("://");
250 urls = urls.concat(item['domain']);
251 urls = urls.concat('/');
252 urls = urls.concat(item['path'] != null ? item['path'] : '');
253 if (item['params'] != null) {
254 urls = urls.concat('?');
255 urls = urls.concat(item['params']);
256 }
257 urls = urls.concat('\n');
258 }
259 return urls;
260 }
261 -------------------------------------------------------------------------
262
263 This approach produces the exact same result, but incurs the cost of
264 joining strings multiple times.
265
266 See the _Concatenating Strings_ recipe for a description of `concat()`.
267
268 ===== Other StringBuffer methods
269
270 In addition to `write()`, the StringBuffer class provides methods to
271 write a list of strings (`writeAll()`), write a numerical character code
272 (`writeCharCode()`), write with an added newline (`writeln()`), and
273 more. The example below shows how to use these methods:
274
275 -------------------------------------------------------------------------------
276 var sb = new StringBuffer();
277 sb.writeln('The Beatles:');
278 sb.writeAll(['John, ', 'Paul, ', 'George, and Ringo']);
279 sb.writeCharCode(33); // charCode for '!'.
280 var beatles = sb.toString(); // 'The Beatles:\nJohn, Paul, George, and Ringo!'
281 -------------------------------------------------------------------------------
282
283
284 === Determining whether a string is empty
285
286 ==== Problem
287
288 You want to know whether a string is empty. You tried `if (string) {...}`, but
289 that did not work.
290
291 ==== Solution
292
293 Use `string.isEmpty`:
294
295 -----------------------------------
296 var emptyString = '';
297 print(emptyString.isEmpty); // true
298 -----------------------------------
299
300 You can also just use `==`:
301
302 ---------------------------------------------------
303 if (string == '') {...} // True if string is empty.
304 ---------------------------------------------------
305
306 A string with a space is not empty:
307
308 -----------------------
309 var space = ' ';
310 print(space.isEmpty); // false
311 -----------------------
312
313 ==== Discussion
314
315 Don't use `if (string)` to test the emptiness of a string. In Dart, all objects
316 except the boolean true evaluate to false, so `if(string)` is always false. You
317 will see a warning in the editor if you use an 'if' statement with a non-boolean
318 in checked mode.
319
320
321 === Removing leading and trailing whitespace
322
323 ==== Problem
324
325 You want to remove spaces, tabs, and other whitespace from the beginning and
326 end of strings.
327
328 ==== Solution
329
330 Use `string.trim()`:
331
332 -----------------------------------------------------------------
333 var space = '\n\r\f\t\v'; // A variety of space characters.
334 var string = '$space X $space';
335 var newString = string.trim(); // 'X'
336 -----------------------------------------------------------------
337
338 The String class has no methods to remove only leading or only trailing
339 whitespace. You can always use a RegExp.
340
341 Remove only leading whitespace:
342
343 -------------------------------------------------------------------------------
344 var newString = string.replaceFirst(new RegExp(r'^\s+'), ''); // 'X \n\r\f\t\v'
345 -------------------------------------------------------------------------------
346
347 Remove only trailing whitespace:
348
349 -------------------------------------------------------------------------------
350 var newString = string.replaceFirst(new RegExp(r'\s+$'), ''); // '\n\r\f\t\v X'
351 -------------------------------------------------------------------------------
352
353
354 === Changing string case
355
356 ==== Problem
357
358 You want to change the case of strings.
359
360 ==== Solution
361
362 Use String's `toUpperCase()` and `toLowerCase()` methods:
363
364 ----------------------------------------------------------------------
365 var theOneILove = 'I love Lucy';
366 theOneILove.toUpperCase(); // 'I LOVE LUCY!'
367 theOneILove.toLowerCase(); // 'i love lucy!'
368
369 // Zeus in modern Greek.
370 var zeus = '\u0394\u03af\u03b1\u03c2'; // 'Δίας'
371 zeus.toUpperCase(); // 'ΔΊΑΣ'
372
373 var resume = '\u0052\u00e9\u0073\u0075\u006d\u00e9'; // 'Résumé'
374 resume.toLowerCase(); // 'résumé'
375 ----------------------------------------------------------------------
376
377 The `toUpperCase()` and `toLowerCase()` methods don't affect the characters of
378 scripts such as Devanagri that don't have distinct letter cases.
379
380 ------------------------------------------------------------------------
381 var chickenKebab = '\u091a\u093f\u0915\u0928 \u0915\u092c\u093e\u092c';
382 // 'चिकन कबाब' (in Devanagari)
383 chickenKebab.toLowerCase(); // 'चिकन कबाब'
384 chickenKebab.toUpperCase(); // 'चिकन कबाब'
385 ------------------------------------------------------------------------
386
387 If a character's case does not change when using `toUpperCase()` and
388 `toLowerCase()`, it is most likely because the character only has one
389 form.
390
391
392 === Handling extended characters that are composed of multiple code units
393
394 ==== Problem
395
396 You want to use emoticons and other special symbols that don't fit into 16
397 bits. How can you create such strings and use them correctly in your code?
398
399 ==== Solution
400
401 You can create an extended character using `'\u{}'` syntax:
402
403 ------------------------------
404 var clef = '\u{1F3BC}'; // 🎼
405 ------------------------------
406
407 ==== Discussion
408
409 Most UTF-16 strings are stored as two-byte (16 bit) code sequences.
410 Since two bytes can only contain the 65,536 characters in the 0x0 to 0xFFFF
411 range, a pair of strings is used to store values in the 0x10000 to 0x10FFFF
412 range. These strings only have semantic meaning as a pair. Individually, they
413 are invalid UTF-16 strings. The term 'surrogate pair' is often used to
414 describe these strings.
415
416 The clef glyph `'\u{1F3BC}'` is composed of the `'\uD83C'` and `'\uDFBC'`
417 surrogate pair.
418
419 You can get an extended string's surrogate pair through its `codeUnits`
420 property:
421
422 -------------------------------------------------------------------------------
423 clef.codeUnits.map((codeUnit) => codeUnit.toRadixString(16));
424 // ['d83c', 'dfbc']
425 -------------------------------------------------------------------------------
426
427 Accessing a surrogate pair member leads to errors, and you should avoid
428 properties and methods that expose it:
429
430 -------------------------------------------------------------------------------
431 print('\ud83c'); // Error: '\ud83c' is not a valid string.
432 print('\udfbc'); // Error: '\udfbc' is not a valid string either.
433 clef.split()[1]; // Error: accessing half of a surrogate pair.
434 print(clef[i];) // Again, error: accessing half of a surrogate pair.
435 -------------------------------------------------------------------------------
436
437 When dealing with strings containing extended characters, you should use the
438 `runes` getter.
439
440 To get the string's length, use `string.runes.length`. Don't use
441 `string.length`:
442
443 -------------------------------------------------------------------------------
444 print(clef.runes.length); // 1
445 print(clef.length); // 2
446 print(clef.codeUnits.length); // 2
447 -------------------------------------------------------------------------------
448
449 To get an individual character or its numeric equivalent, index the rune list:
450
451 --------------------------------------------------------------
452 print(clef.runes.toList()[0]); // 127932 ('\u{1F3BC}')
453 --------------------------------------------------------------
454
455 To get the string's characters as a list, map the string runes:
456
457 ---------------------------------------------------------------------------
458 var clef = '\u{1F3BC}'; // 🎼
459 var title = '$clef list:'
460 print(subject.runes.map((rune) => new String.fromCharCode(rune)).toList());
461 // ['🎼', ' ', 'l', 'i', 's', 't', ':']
462 ---------------------------------------------------------------------------
463
464
465 === Converting between characters and numerical codes
466
467 ==== Problem
468
469 You want to convert string characters into numerical codes and vice versa.
470 You want to do this because sometimes you need to compare characters in a string
471 to numerical values coming from another source. Or, maybe you want to split a
472 string and then operate on each character.
473
474 ==== Solution
475
476 Use the `runes` getter to get a string's code points:
477
478 -----------------------------------------------------------------------------
479 'Dart'.runes.toList(); // [68, 97, 114, 116]
480
481 var smileyFace = '\u263A'; // ☺
482 print(smileyFace.runes.toList()); // [9786], (equivalent to ['\u263A']).
483
484 var clef = '\u{1F3BC}'; // 🎼
485 print(clef.runes.toList()); // [127932], (equivalent to ['\u{1F3BC}']).
486 -----------------------------------------------------------------------------
487
488 Use `string.codeUnits` to get a string's UTF-16 code units:
489
490 ----------------------------------------------------
491 'Dart'.codeUnits.toList(); // [68, 97, 114, 116]
492 smileyFace.codeUnits.toList(); // [9786]
493 clef.codeUnits.toList(); // [55356, 57276]
494 ----------------------------------------------------
495
496 ===== Using codeUnitAt() to get individual code units
497
498 To get the code unit at a particular index, use `codeUnitAt()`:
499
500 ----------------------------------------------------------------------
501 'Dart'.codeUnitAt(0); // 68
502 smileyFace.codeUnitAt(0); // 9786 (the decimal value of '\u263A')
503 clef.codeUnitAt(0); // 55356 (does not represent a legal string)
504 ----------------------------------------------------------------------
505
506 ==== Converting numerical codes to strings
507
508 You can generate a new string from numerical codes using the factory
509 `String.fromCharCodes(charCodes)`. You can pass either runes or code units and
510 `String.fromCharCodes(charCodes)` can tell the difference and do the right
511 thing automatically:
512
513 -------------------------------------------------------------------------------
514 print(new String.fromCharCodes([68, 97, 114, 116])); // 'Dart'
515
516 print(new String.fromCharCodes([73, 32, 9825, 32, 76, 117, 99, 121]));
517 // 'I ♡ Lucy'
518
519 // Passing code units representing the surrogate pair.
520 print(new String.fromCharCodes([55356, 57276])); // 🎼
521
522 // Passing runes.
523 print(new String.fromCharCodes([127932])); // 🎼
524 -------------------------------------------------------------------------------
525
526 You can use the `String.fromCharCode()` factory to convert a single rune
527 or code unit to a string:
528
529 ---------------------------------------
530 new String.fromCharCode(68); // 'D'
531 new String.fromCharCode(9786); // ☺
532 new String.fromCharCode(127932); // 🎼
533 ---------------------------------------
534
535 Creating a string with only one half of a surrogate pair is permitted,
536 but not recommended.
537
538
539 === Calculating the length of a string
540
541 ==== Problem
542
543 You want to get the length of a string, but are not sure how to calculate the
544 length correctly when working with variable length Unicode characters.
545
546 ==== Solution
547
548 Use `string.runes.length` to get the number of characters in a string.
549
550 -----------------------------------------
551 print('I love music'.runes.length); // 12
552 -----------------------------------------
553
554 You can safely use `string.runes.length` to get the length of strings that
555 contain extended characters:
556
557 -----------------------------------------
558 var clef = '\u{1F3BC}'; // 🎼
559 var subject = '$clef list:'; //
560 var music = 'I $hearts $clef'; // 'I ♡ 🎼 '
561
562 clef.runes.length; // 1
563 music.runes.length // 5
564 -----------------------------------------
565
566 ==== Discussion
567
568 You can directly use a string's `length` property (minus `runes`). This returns
569 the string's code unit length. Using `string.length` produces the same length
570 as `string.runes.length` for most unicode characters.
571
572 For extended characters, the code unit length is one more than the rune
573 length:
574
575 ------------------------------------------
576 clef.length; // 2
577
578 var music = 'I $hearts $clef'; // 'I ♡ 🎼 '
579 music.length; // 6
580 ------------------------------------------
581
582 Unless you specifically need the code unit length of a string, use
583 `string.runes.length`.
584
585 ===== Working with combined characters
586
587 It is tempting to brush aside the complexity involved in dealing with runes and
588 code units and base the length of the string on the number of characters it
589 appears to have. Anyone can tell that 'Dart' has four characters, and 'Amelié'
590 has six, right? Almost. The length of 'Dart' is indeed four, but the length of
591 'Amelié' depends on how that string was constructed:
592
593 ---------------------------------------------------
594 var name = 'Ameli\u00E9'; // 'Amelié'
595 var anotherName = 'Ameli\u0065\u0301'; // 'Amelié'
596 print(name.length); // 6
597 print(anotherName.length); // 7
598 ---------------------------------------------------
599
600 Both `name` and `anotherName` return strings that look the same, but where
601 the 'é' is constructed using a different number of runes. This makes it
602 impossible to know the length of these strings by just looking at them.
603
604
605 === Processing a string one character at a time
606
607 ==== Problem
608
609 You want to do something with each character in a string.
610
611 ==== Solution
612
613 Map the results of calling `string.split('')`:
614
615 ----------------------------------------------------------
616 var lang= 'Dart';
617
618 // ['*D*', '*a*', '*r*', '*t*']
619 print(lang.split('').map((char) => '*${char}*').toList());
620
621 var smileyFace = '\u263A';
622 var happy = 'I am $smileyFace';
623 print(happy.split('')); // ['I', ' ', 'a', 'm', ' ', '☺']
624 ----------------------------------------------------------
625
626
627 Or, loop over the characters of a string:
628
629 --------------------------------------------
630 var list = [];
631 for(var i = 0; i < lang.length; i++) {
632 list.add('*${lang[i]}*');
633 }
634
635 print(list); // ['*D*', '*a*', '*r*', '*t*']
636 --------------------------------------------
637
638 Or, map the string runes:
639
640 ------------------------------------------------------------------------
641 // ['*D*', '*a*', '*r*', '*t*']
642 var charList = "Dart".runes.map((rune) {
643 return '*${new String.fromCharCode(rune)}*').toList();
644 });
645
646 // [[73, 'I'], [32, ' '], [97, 'a'], [109, 'm'], [32, ' '], [9786, '☺']]
647 var runeList = happy.runes.map((rune) {
648 return [rune, new String.fromCharCode(rune)]).toList();
649 });
650 ------------------------------------------------------------------------
651
652 When working with extended characters, you should always map the string runes.
653 Don't use `split('')` and avoid indexing an extended string. See the _Handling
654 extended characters that are composed of multiple code units_ recipe for
655 special considerations when working with extended strings.
656
657
658 === Splitting a string into substrings
659
660 ==== Problem
661
662 You want to split a string into substrings using a delimiter or a pattern.
663
664 ==== Solution
665
666 Use the `split()` method with a string or a RegExp as an argument.
667
668 -------------------------------------
669 var smileyFace = '\u263A';
670 var happy = 'I am $smileyFace';
671 happy.split(' '); // ['I', 'am', '☺']
672 -------------------------------------
673
674 Here is an example of using `split()` with a RegExp:
675
676 --------------------------------------------------------------
677 var nums = '2/7 3 4/5 3~/5';
678 var numsRegExp = new RegExp(r'(\s|/|~/)');
679 nums.split(numsRegExp); // ['2', '7', '3', '4', '5', '3', '5']
680 --------------------------------------------------------------
681
682 In the code above, the string `nums` contains various numbers, some of which
683 are expressed as fractions or as int-divisions. A RegExp splits the string to
684 extract just the numbers.
685
686 You can perform operations on the matched and unmatched portions of a string
687 when using `split()` with a RegExp:
688
689 ----------------------------------------------------------------
690 var phrase = 'Eats SHOOTS leaves';
691
692 var newPhrase = phrase.splitMapJoin((new RegExp(r'SHOOTS')),
693 onMatch: (m) => '*${m.group(0).toLowerCase()}*',
694 onNonMatch: (n) => n.toUpperCase());
695
696 print(newPhrase); // 'EATS *shoots* LEAVES'
697
698 ----------------------------------------------------------------
699
700 The RegExp matches the middle word ('SHOOTS'). A pair of callbacks are
701 registered to transform the matched and unmatched substrings before the
702 substrings are joined together again.
703
704
705 === Determining whether a string contains another string
706
707 ==== Problem
708
709 You want to find out whether a string is the substring of another string.
710
711 ==== Solution
712
713 Use `string.contains()`:
714
715 ---------------------------------------------
716 var fact = 'Dart strings are immutable';
717 print(fact.contains('immutable')); // True.
718 ---------------------------------------------
719
720 You can use a second argument to specify where in the string to start looking:
721
722 -----------------------------------------
723 print(fact.contains('Dart', 2)); // False
724 -----------------------------------------
725
726 ==== Discussion
727
728 The String class provides a couple of shortcuts for testing whether a
729 string is a substring of another:
730
731 ------------------------------------------
732 print(string.startsWith('Dart')); // True.
733 print(string.endsWith('e')); // True.
734 ------------------------------------------
735
736 You can also use `string.indexOf()`, which returns -1 if the substring
737 is not found within a string, and otherwise returns the matching index:
738
739 ---------------------------------------------------------------------------
740 var found = string.indexOf('art') != -1; // True, `art` is found in `Dart`.
741 ---------------------------------------------------------------------------
742
743 You can also use a RegExp and `hasMatch()`:
744
745 ------------------------------------------------------------------------
746 var found = new RegExp(r'ar[et]').hasMatch(string);
747 // True, 'art' and 'are' match.
748 ------------------------------------------------------------------------
749
750 === Finding matches of a RegExp pattern in a string
751
752 ==== Problem
753
754 You want to use RegExp to match a pattern in a string, and want to be
755 able to access the matches.
756
757 ==== Solution
758
759 Construct a regular expression using the RegExp class, and find matches
760 using the `allMatches()` method:
761
762 -------------------------------------------------------------------------
763 var neverEatingThat = 'Not with a fox, not in a box';
764 var regExp = new RegExp(r'[fb]ox');
765 List matches = regExp.allMatches(neverEatingThat);
766 print(matches.map((match) => match.group(0)).toList()); // ['fox', 'box']
767 -------------------------------------------------------------------------
768
769 ==== Discussion
770
771 You can query the object returned by `allMatches()` to find out the
772 number of matches:
773
774 -----------------------------------------
775 var howManyMatches = matches.length; // 2
776 -----------------------------------------
777
778 To find the first match, use `firstMatch()`:
779
780 ----------------------------------------------------------------------
781 var firstMatch = RegExp.firstMatch(neverEatingThat).group(0); // 'fox'
782 ----------------------------------------------------------------------
783
784 To directly get the matched string, use `stringMatch()`:
785
786 ------------------------------------------------------------
787 print(regExp.stringMatch(neverEatingThat)); // 'fox'
788 print(regExp.stringMatch('I like bagels and lox')); // null
789 ------------------------------------------------------------
790
791 === Substituting strings based on RegExp matches
792
793 ==== Problem
794
795 You want to match substrings within a string and make substitutions
796 based on the matches.
797
798 ==== Solution
799
800 Construct a regular expression using the RegExp class and make
801 replacements using `replaceAll()` method:
802
803 -------------------------------------------------------------------------
804 var resume = 'resume'.replaceAll(new RegExp(r'e'), '\u00E9'); // 'résumé'
805 -------------------------------------------------------------------------
806
807 If you want to replace just the first match, use `replaceFirst()`:
808
809 -----------------------------------------------------------------------
810 // Replace the first match of one or more zeros with an empty string.
811 var smallNum = '0.0001'.replaceFirst(new RegExp(r'0+'), ''); // '.0001'
812 -----------------------------------------------------------------------
813
814 You can use `replaceAllMatched()` to register a function that modifies the
815 matches:
816
817 ---------------------------------------------------------
818 var heart = '\u2661'; // '♡'
819 var string = 'I like Ike but I $heart Lucy';
820 var regExp = new RegExp(r'[A-Z]\w+');
821 var newString = string.replaceAllMapped(regExp, (match) {
822 return match.group(0).toUpperCase()
823 });
824 print(newString); // 'I like IKE but I ♡ LUCY'
825 ---------------------------------------------------------
OLDNEW
« no previous file with comments | « no previous file | book.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698