diff --git a/src/content/codelabs/iterables.md b/src/content/codelabs/iterables.md index 4266155f45..be754a7330 100644 --- a/src/content/codelabs/iterables.md +++ b/src/content/codelabs/iterables.md @@ -306,68 +306,75 @@ All the elements in the test data are [strings][String class]; you can check the class documentation for help. ```dart:run-dartpad:theme-dark:ga_id-practice_writing_a_test_predicate -{$ begin main.dart $} // Implement the predicate of singleWhere // with the following conditions // * The element contains the character `'a'` // * The element starts with the character `'M'` String singleWhere(Iterable items) { - return items.singleWhere(TODO('Implement predicate')); + return items.singleWhere(TODO('Implement the outlined predicate.')); } -{$ end main.dart $} -{$ begin solution.dart $} -String singleWhere(Iterable items) { - return items.singleWhere( - (element) => element.startsWith('M') && element.contains('a')); -} -{$ end solution.dart $} -{$ begin test.dart $} -const items = [ - 'Salad', - 'Popcorn', - 'Milk', - 'Toast', - 'Sugar', - 'Mozzarella', - 'Tomato', - 'Egg', - 'Water', -]; +// The following code is used to provide feedback on your solution. +// Try your best first and do not modify. void main() { + const items = [ + 'Salad', + 'Popcorn', + 'Milk', + 'Toast', + 'Sugar', + 'Mozzarella', + 'Tomato', + 'Egg', + 'Water', + ]; + try { final str = singleWhere(items); if (str == 'Mozzarella') { - _result(true); + print('Success. All tests passed!'); } else { - _result(false, [ - 'Tried calling singleWhere, but received $str instead of the expected ' - 'value \'Mozzarella\'' - ]); + print( + 'Tried calling singleWhere, but received $str instead of ' + 'the expected value \'Mozzarella\'', + ); } } on StateError catch (stateError) { - _result(false, [ + print( 'Tried calling singleWhere, but received a StateError: ${stateError.message}. ' - 'singleWhere will fail if 0 or many elements match the ' - 'predicate' - ]); + 'singleWhere will fail if 0 or many elements match the predicate.', + ); } on UnimplementedError { - _result(false, [ - 'Tried running `singleWhere`, but received an error. Did you implement the method?' - ]); - return; + print( + 'Tried running `singleWhere`, but received an error. ' + 'Did you implement the function?', + ); } catch (e) { - _result(false, [ - 'Tried calling singleWhere, but received an exception: $e' - ]); + print('Tried calling singleWhere, but received an exception: $e'); } } -{$ end test.dart $} -{$ begin hint.txt $} -Use the methods `contains()` and `startsWith()` from the `String` class. -{$ end hint.txt $} ``` +
+ Hint + + Your solution might make use of the `contains` and `startsWith` + methods from the `String` class. + +
+ +
+ Solution + + ```dart + String singleWhere(Iterable items) { + return items.singleWhere( + (element) => element.startsWith('M') && element.contains('a')); + } + ``` + +
+ ## Checking conditions When working with `Iterable`, sometimes you need to verify that @@ -456,139 +463,147 @@ Use `any()` and `every()` to implement two functions: * Return `true` if all users are 14 or older. ```dart:run-dartpad:theme-dark:height-395px:ga_id-verify_iterable -{$ begin main.dart $} -bool anyUserUnder18(Iterable users) { - TODO('Implement this method'); -} - -bool everyUserOver13(Iterable users) { - TODO('Implement this method'); -} - -class User { - String name; - int age; - - User( - this.name, - this.age, - ); -} -{$ end main.dart $} -{$ begin solution.dart $} bool anyUserUnder18(Iterable users) { - return users.any((user) => user.age < 18); + TODO('Implement the anyUserUnder18 function.'); } bool everyUserOver13(Iterable users) { - return users.every((user) => user.age > 13); + TODO('Implement the everyUserOver13 function.'); } class User { - String name; - int age; + final String name; + final int age; User( this.name, this.age, ); } -{$ end solution.dart $} -{$ begin test.dart $} -var users = [ - User('Alice', 21), - User('Bob', 17), - User('Claire', 52), - User('David', 14), -]; +// The following code is used to provide feedback on your solution. +// Try your best first and do not modify. void main() { + final users = [ + User('Alice', 21), + User('Bob', 17), + User('Claire', 52), + User('David', 14), + ]; + try { - var out = anyUserUnder18(users); + final out = anyUserUnder18(users); if (!out) { - _result(false, ['Looks like `anyUserUnder18` is wrong. Keep trying!']); + print('Looks like `anyUserUnder18` is wrong. Keep trying!'); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `anyUserUnder18`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `anyUserUnder18`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, - ['Tried running `anyUserUnder18`, but received an exception: $e']); + print('Tried running `anyUserUnder18`, but received an exception: $e'); return; } try { // with only one user older than 18, should be false - var out = anyUserUnder18([User('Alice', 21)]); + final out = anyUserUnder18([User('Alice', 21)]); if (out) { - _result(false, [ - 'Looks like `anyUserUnder18` is wrong. What if all users are over 18?' - ]); + print( + 'Looks like `anyUserUnder18` is wrong. What if all users are over 18?'); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `anyUserUnder18`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `anyUserUnder18`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `anyUserUnder18([User("Alice", 21)])`, but received an exception: $e' - ]); + print( + 'Tried running `anyUserUnder18([User("Alice", 21)])`, ' + 'but received an exception: $e', + ); return; } try { - var out = everyUserOver13(users); + final out = everyUserOver13(users); if (!out) { - _result(false, [ - 'Looks like `everyUserOver13` is wrong. There are no users under 13!' - ]); + print( + 'Looks like `everyUserOver13` is wrong. ' + 'There are no users under 13!', + ); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `everyUserOver13`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `everyUserOver13`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `everyUserOver13`, but received an exception: $e' - ]); + print( + 'Tried running `everyUserOver13`, ' + 'but received an exception: $e', + ); return; } try { - var out = everyUserOver13([User('Dan', 12)]); + final out = everyUserOver13([User('Dan', 12)]); if (out) { - _result(false, [ - 'Looks like `everyUserOver13` is wrong. There is at least one user under 13!' - ]); + print( + 'Looks like `everyUserOver13` is wrong. ' + 'There is at least one user under 13!', + ); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `everyUserOver13`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `everyUserOver13`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `everyUserOver13([User(\'Dan\', 12)])`, but received an exception: $e' - ]); + print( + 'Tried running `everyUserOver13([User(\'Dan\', 12)])`, ' + 'but received an exception: $e', + ); return; } - _result(true); + print('Success. All tests passed!'); } -{$ end test.dart $} -{$ begin hint.txt $} -Use the methods `any()` and `every()` to compare the user age. -{$ end hint.txt $} ``` +
+ Hint + + Remember to use the `any` and `every` methods from the `Iterable` class. + For help and examples using these methods, refer to + the [earlier discussion of them](#example-using-any-and-every). + +
+ +
+ Solution + + ```dart + bool anyUserUnder18(Iterable users) { + return users.any((user) => user.age < 18); + } + + bool everyUserOver13(Iterable users) { + return users.every((user) => user.age > 13); + } + ``` + +
+ :::secondary Quick review * Although you can use `for-in` loops to check conditions, there are better ways to do that. @@ -725,97 +740,108 @@ Use `where()` to implement two functions: names of length 3 or less. ```dart:run-dartpad:theme-dark:height-380px:ga_id-filtering_elements_from_a_list -{$ begin main.dart $} -Iterable filterOutUnder21(Iterable users) { - TODO('Implement this method'); -} - -Iterable findShortNamed(Iterable users) { - TODO('Implement this method'); -} - -class User { - String name; - int age; - - User( - this.name, - this.age, - ); -} -{$ end main.dart $} -{$ begin solution.dart $} Iterable filterOutUnder21(Iterable users) { - return users.where((user) => user.age >= 21); + TODO('Implement the filterOutUnder21 function.'); } Iterable findShortNamed(Iterable users) { - return users.where((user) => user.name.length <= 3); + TODO('Implement the findShortNamed function.'); } class User { - String name; - int age; + final String name; + final int age; User( this.name, this.age, ); } -{$ end solution.dart $} -{$ begin test.dart $} -var users = [ - User('Alice', 21), - User('Bob', 17), - User('Claire', 52), - User('Dan', 12), -]; +// The following code is used to provide feedback on your solution. +// Try your best first and do not modify. void main() { + final users = [ + User('Alice', 21), + User('Bob', 17), + User('Claire', 52), + User('Dan', 12), + ]; + try { - var out = filterOutUnder21(users); + final out = filterOutUnder21(users); if (out.any((user) => user.age < 21) || out.length != 2) { - _result(false, ['Looks like `filterOutUnder21` is wrong, there are exactly two users with age under 21. Keep trying!']); + print( + 'Looks like `filterOutUnder21` is wrong, there are ' + 'exactly two users with age under 21. Keep trying!', + ); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `filterOutUnder21`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `filterOutUnder21`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `filterOutUnder21`, but received an exception: ${e.runtimeType}' - ]); + print( + 'Tried running `filterOutUnder21`, ' + 'but received an exception: ${e.runtimeType}', + ); return; } try { - var out = findShortNamed(users); + final out = findShortNamed(users); if (out.any((user) => user.name.length > 3) || out.length != 2) { - _result(false, ['Looks like `findShortNamed` is wrong, there are exactly two users with a three letter name. Keep trying!']); + print( + 'Looks like `findShortNamed` is wrong, there are ' + 'exactly two users with a three letter name. Keep trying!', + ); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `findShortNamed`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `findShortNamed`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `findShortNamed`, but received an exception: ${e.runtimeType}' - ]); + print( + 'Tried running `findShortNamed`, ' + 'but received an exception: ${e.runtimeType}', + ); return; } - - _result(true); + + print('Success. All tests passed!'); } -{$ end test.dart $} -{$ begin hint.txt $} -Use the `where()` method to implement the filters. -{$ end hint.txt $} ``` +
+ Hint + + Remember to take advantage of the `where` method from the `Iterable` class. + For help and examples using `where`, refer to + the [earlier discussion of it](#example-using-where). + +
+ +
+ Solution + + ```dart + Iterable filterOutUnder21(Iterable users) { + return users.where((user) => user.age >= 21); + } + + Iterable findShortNamed(Iterable users) { + return users.where((user) => user.name.length <= 3); + } + ``` + +
+ :::secondary Quick review * Filter the elements of an `Iterable` with `where()`. * The output of `where()` is another `Iterable`. @@ -880,75 +906,85 @@ Each string in the `Iterable` must follow this format: `'{name} is {age}'`—for example `'Alice is 21'`. ```dart:run-dartpad:theme-dark:height-310px:ga_id-mapping_to_a_different_type -{$ begin main.dart $} Iterable getNameAndAges(Iterable users) { - TODO('Implement this method'); + TODO('Implement the getNameAndAges function.'); } class User { - String name; - int age; + final String name; + final int age; User( this.name, this.age, ); } -{$ end main.dart $} -{$ begin solution.dart $} -Iterable getNameAndAges(Iterable users) { - return users.map((user) => '${user.name} is ${user.age}'); -} - -class User { - String name; - int age; - - User( - this.name, - this.age, - ); -} -{$ end solution.dart $} -{$ begin test.dart $} -var users = [ - User('Alice', 21), - User('Bob', 17), - User('Claire', 52), -]; +// The following code is used to provide feedback on your solution. +// Try your best first and do not modify. void main() { + final users = [ + User('Alice', 21), + User('Bob', 17), + User('Claire', 52), + ]; + try { final out = getNameAndAges(users).toList(); if (!_listEquals(out, ['Alice is 21', 'Bob is 17', 'Claire is 52'])) { - _result(false, ['Looks like `getNameAndAges` is wrong. Keep trying! The output was $out']); + print( + 'Looks like `getNameAndAges` is wrong. Keep trying! ' + 'The output was: $out', + ); return; } - _result(true); } on UnimplementedError { - _result(false, [ - 'Tried running `getNameAndAges`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `getNameAndAges`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, ['Tried running the method, but received an exception: $e']); + print('Tried running the function, but received an exception: $e'); + return; } + + print('Success. All tests passed!'); } bool _listEquals(List? a, List? b) { if (a == null) return b == null; if (b == null || a.length != b.length) return false; - for (int index = 0; index < a.length; index += 1) { + for (var index = 0; index < a.length; index += 1) { if (a[index] != b[index]) return false; } return true; } -{$ end test.dart $} -{$ begin hint.txt $} -Use `map()` to create a String with the values of `user.name` and `user.age`. -{$ end hint.txt $} ``` +
+ Hint + + Remember to take advantage of the `map` method from the `Iterable` class. + For help and examples using `map`, refer to + the [earlier discussion of it](#example-using-map-to-change-elements). + + To concatenate multiple values into a single string, consider + using [string interpolation](/language/built-in-types#string-interpolation). + +
+ +
+ Solution + + ```dart + Iterable getNameAndAges(Iterable users) { + return users.map((user) => '${user.name} is ${user.age}'); + } + ``` + +
+ :::secondary Quick review * `map()` applies a function to all the elements of an `Iterable`. * The output of `map()` is another `Iterable`. @@ -1000,17 +1036,16 @@ Part 3: Implement `validEmailAddresses()`. an `EmailAddress` is valid. ```dart:run-dartpad:theme-dark:height-600px:ga_id-putting_it_all_together -{$ begin main.dart $} Iterable parseEmailAddresses(Iterable strings) { - TODO('Implement this method'); + TODO('Implement the parseEmailAddresses function.'); } bool anyInvalidEmailAddress(Iterable emails) { - TODO('Implement this method'); + TODO('Implement the anyInvalidEmailAddress function.'); } Iterable validEmailAddresses(Iterable emails) { - TODO('Implement this method'); + TODO('Implement the validEmailAddresses function.'); } class EmailAddress { @@ -1021,75 +1056,44 @@ class EmailAddress { @override bool operator ==(Object other) => identical(this, other) || - other is EmailAddress && - address == other.address; + other is EmailAddress && address == other.address; @override int get hashCode => address.hashCode; @override - String toString() { - return 'EmailAddress{address: $address}'; - } -} -{$ end main.dart $} -{$ begin solution.dart $} -Iterable parseEmailAddresses(Iterable strings) { - return strings.map((s) => EmailAddress(s)); -} - -bool anyInvalidEmailAddress(Iterable emails) { - return emails.any((email) => !isValidEmailAddress(email)); -} - -Iterable validEmailAddresses(Iterable emails) { - return emails.where((email) => isValidEmailAddress(email)); + String toString() => 'EmailAddress{address: $address}'; } -class EmailAddress { - final String address; - - EmailAddress(this.address); - - @override - bool operator ==(Object other) => - identical(this, other) || - other is EmailAddress && - runtimeType == other.runtimeType && - address == other.address; - - @override - int get hashCode => address.hashCode; - - @override - String toString() { - return 'EmailAddress{address: $address}'; +// The following code is used to provide feedback on your solution. +// Try your best first and do not modify. +void main() { + const input = [ + 'ali@gmail.com', + 'bobgmail.com', + 'cal@gmail.com', + ]; + + const correctInput = ['dash@gmail.com', 'sparky@gmail.com']; + + bool _listEquals(List? a, List? b) { + if (a == null) return b == null; + if (b == null || a.length != b.length) return false; + for (var index = 0; index < a.length; index += 1) { + if (a[index] != b[index]) return false; + } + return true; } -} -{$ end solution.dart $} -{$ begin test.dart $} -const input = [ - 'ali@gmail.com', - 'bobgmail.com', - 'cal@gmail.com', -]; - -const correctInput = ['dash@gmail.com', 'sparky@gmail.com']; - -bool isValidEmailAddress(EmailAddress email) { - return email.address.contains('@'); -} -void main() { - Iterable emails; - Iterable correctEmails; + final Iterable emails; + final Iterable correctEmails; try { emails = parseEmailAddresses(input); correctEmails = parseEmailAddresses(correctInput); if (emails.isEmpty) { - _result(false, [ - 'Tried running `parseEmailAddresses`, but received an empty list.' - ]); + print( + 'Tried running `parseEmailAddresses`, but received an empty list.', + ); return; } if (!_listEquals(emails.toList(), [ @@ -1097,92 +1101,106 @@ void main() { EmailAddress('bobgmail.com'), EmailAddress('cal@gmail.com'), ])) { - _result(false, ['Looks like `parseEmailAddresses` is wrong. Keep trying!']); + print('Looks like `parseEmailAddresses` is wrong. Keep trying!'); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `parseEmailAddresses`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `parseEmailAddresses`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `parseEmailAddresses`, but received an exception: $e' - ]); + print( + 'Tried running `parseEmailAddresses`, ' + 'but received an exception: $e', + ); return; } try { final out = anyInvalidEmailAddress(emails); if (!out) { - _result(false, [ - 'Looks like `anyInvalidEmailAddress` is wrong. Keep trying! The result should be false with at least one invalid address.' - ]); + print( + 'Looks like `anyInvalidEmailAddress` is wrong. Keep trying! ' + 'The result should be false with at least one invalid address.', + ); return; } final falseOut = anyInvalidEmailAddress(correctEmails); if (falseOut) { - _result(false, [ - 'Looks like `anyInvalidEmailAddress` is wrong. Keep trying! The result should be false with all valid addresses.' - ]); + print( + 'Looks like `anyInvalidEmailAddress` is wrong. Keep trying! ' + 'The result should be false with all valid addresses.', + ); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `anyInvalidEmailAddress`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `anyInvalidEmailAddress`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running `anyInvalidEmailAddress`, but received an exception: $e' - ]); + print( + 'Tried running `anyInvalidEmailAddress`, but received an exception: $e'); return; } try { final valid = validEmailAddresses(emails); if (emails.isEmpty) { - _result(false, [ - 'Tried running `validEmailAddresses`, but received an empty list.' - ]); + print('Tried running `validEmailAddresses`, but received an empty list.'); return; } if (!_listEquals(valid.toList(), [ EmailAddress('ali@gmail.com'), EmailAddress('cal@gmail.com'), ])) { - _result(false, ['Looks like `validEmailAddresses` is wrong. Keep trying!']); + print('Looks like `validEmailAddresses` is wrong. Keep trying!'); return; } } on UnimplementedError { - _result(false, [ - 'Tried running `validEmailAddresses`, but received an error. Did you implement the method?' - ]); + print( + 'Tried running `validEmailAddresses`, but received an error. ' + 'Did you implement the function?', + ); return; } catch (e) { - _result(false, [ - 'Tried running the `validEmailAddresses`, but received an exception: $e' - ]); + print( + 'Tried running the `validEmailAddresses`, ' + 'but received an exception: $e', + ); return; } - _result(true); + print('Success. All tests passed!'); } -bool _listEquals(List? a, List? b) { - if (a == null) return b == null; - if (b == null || a.length != b.length) return false; - for (int index = 0; index < a.length; index += 1) { - if (a[index] != b[index]) return false; - } - return true; +bool isValidEmailAddress(EmailAddress email) { + return email.address.contains('@'); } -{$ end test.dart $} -{$ begin hint.txt $} -Use the methods `map()`, `any()`, and `where()` to solve the exercise. -{$ end hint.txt $} ``` +
+ Solution + + ```dart + Iterable parseEmailAddresses(Iterable strings) { + return strings.map((s) => EmailAddress(s)); + } + + bool anyInvalidEmailAddress(Iterable emails) { + return emails.any((email) => !isValidEmailAddress(email)); + } + + Iterable validEmailAddresses(Iterable emails) { + return emails.where((email) => isValidEmailAddress(email)); + } + ``` + +
+ ## What's next Congratulations, you finished the codelab! diff --git a/src/content/language/built-in-types.md b/src/content/language/built-in-types.md index afd2faa657..0849c9006d 100644 --- a/src/content/language/built-in-types.md +++ b/src/content/language/built-in-types.md @@ -187,9 +187,11 @@ var s3 = 'It\'s easy to escape the string delimiter.'; var s4 = "It's even easier to use the other delimiter."; ``` + + You can put the value of an expression inside a string by using `${`*`expression`*`}`. If the expression is an identifier, you can skip -the {}. To get the string corresponding to an object, Dart calls the +the `{}`. To get the string corresponding to an object, Dart calls the object's `toString()` method.