feat(curriculum): add case converter project to teach list comprehension (#52569)

Co-authored-by: Dario-DC <105294544+Dario-DC@users.noreply.github.com>
Co-authored-by: Estefania Cassingena Navone <85124911+estefaniacn@users.noreply.github.com>
Co-authored-by: moT01 <20648924+moT01@users.noreply.github.com>
This commit is contained in:
Farhan Hasin Chowdhury
2023-12-20 11:02:01 +06:00
committed by GitHub
parent 3846e46483
commit 49aef261fb
25 changed files with 1344 additions and 4 deletions
+31 -4
View File
@@ -557,10 +557,7 @@
"In these projects, you'll need to fetch data and parse a dataset, then use D3 to create different data visualizations. Finish them all to earn your Data Visualization certification."
]
},
"d3-dashboard": {
"title": "D3 Dashboard",
"intro": ["", ""]
}
"d3-dashboard": { "title": "D3 Dashboard", "intro": ["", ""] }
}
},
"relational-database": {
@@ -769,6 +766,29 @@
"Through this project, you'll gain valuable experience in working with numerical computations and string manipulation while implementing the Luhn Algorithm."
]
},
"learn-list-comprehension-by-building-a-case-converter-program": {
"title": "Learn Python List Comprehension By Building a Case Converter Program",
"intro": [
"A list comprehension in Python is a way to construct a new list from an iterable types such as lists, tuples, and strings without using a for loop or the `.append()` list method",
"In this project, you will write a program that takes a string formatted in camel or pascal case and converts that to snake case. The project has two phases.",
"During the first phase, you will use a for loop to implement the program.",
"Then in the second phase you will learn about applying list comprehension instead of a loop to achieve the same results."
]
},
"learn-regular-expressions-by-building-a-password-generator": {
"title": "Learn Regular Expressions by Building a Password Generator",
"intro": [
"In Python, a module is a file containing a set of statements and definitions that you can use in your code.",
"In this project, you'll learn how to import and use modules from the Python standard library and how to use regular expressions while building your own password generator program."
]
},
"learn-algorithm-design-by-building-the-shortest-path-algorithm": {
"title": "Learn Algorithm Design by Building the Shortest Path Algorithm",
"intro": [
"Algorithms are step-by-step procedures used to perform calculations and solve computational problems.",
"In this project, you'll learn how to use functions, loops, conditional statements, dictionary comprehensions and more to design and implement the shortest path algorithm."
]
},
"learn-recursion-by-solving-the-tower-of-hanoi-puzzle": {
"title": "Learn Recursion by Solving the Tower of Hanoi Puzzle",
"intro": [
@@ -776,6 +796,13 @@
"In this project, you'll start with an iterative approach to solve the tower of Hanoi mathematical puzzle and then you'll learn how to implement a recursive solution."
]
},
"learn-data-structures-by-building-the-merge-sort-algorithm": {
"title": "Learn Data Structures by Building the Merge Sort Algorithm",
"intro": [
"The merge sort algorithm is a sorting algorithm based on the divide and conquer principle.",
"In this project, you'll learn how to interact with data structures by sorting a list of random numbers using the merge sort algorithm."
]
},
"learn-classes-and-objects-by-building-a-sudoku-solver": {
"title": "Learn Classes and Objects by Building a Sudoku Solver",
"intro": [
@@ -0,0 +1,10 @@
---
title: Introduction to the Learn Python List Comprehension By Building a Case Converter Program
block: learn-list-comprehension-by-building-a-case-converter-program
superBlock: upcoming-python
isBeta: true
---
## Introduction to the Learn Python List Comprehension By Building a Case Converter Program
This is a test for the new project-based curriculum.
@@ -0,0 +1,104 @@
{
"name": "Learn Python List Comprehension By Building a Case Converter Program",
"isUpcomingChange": false,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"dashedName": "learn-list-comprehension-by-building-a-case-converter-program",
"order": 3,
"time": "5 hours",
"template": "",
"required": [],
"superBlock": "scientific-computing-with-python",
"isBeta": true,
"challengeOrder": [
{
"id": "657e928716b77b2277980276",
"title": "Step 1"
},
{
"id": "657ed53c19461d4b95c4757a",
"title": "Step 2"
},
{
"id": "657ee28cefc4945568287673",
"title": "Step 3"
},
{
"id": "657ef2a86d4e545cec9a85fb",
"title": "Step 4"
},
{
"id": "657efa642593c5746acc5c81",
"title": "Step 5"
},
{
"id": "657efce98e958b75df86b305",
"title": "Step 6"
},
{
"id": "657efdcf7fe23b76c0cff9ec",
"title": "Step 7"
},
{
"id": "657effaa2a5e0277d71f9cbe",
"title": "Step 8"
},
{
"id": "657f0044be09db790b1eb1c5",
"title": "Step 9"
},
{
"id": "657f01ae9aea647b27402d3e",
"title": "Step 10"
},
{
"id": "657f025ec86c3d7c4177b6be",
"title": "Step 11"
},
{
"id": "657f0353c9523d7d896873ea",
"title": "Step 12"
},
{
"id": "657f04ed0035f47ed04d0f1f",
"title": "Step 13"
},
{
"id": "657f28a0482132aca51a9212",
"title": "Step 14"
},
{
"id": "657f425dbab54e11993c80f0",
"title": "Step 15"
},
{
"id": "657f4345abe7f2161f99f1ad",
"title": "Step 16"
},
{
"id": "657f43d341a0dd17120cdb08",
"title": "Step 17"
},
{
"id": "657f456223b8c1187b461987",
"title": "Step 18"
},
{
"id": "657f465f8e718b19c5105ae5",
"title": "Step 19"
},
{
"id": "657f47b12c51e41b3149e584",
"title": "Step 20"
},
{
"id": "657f4a4a5828a01de04b652f",
"title": "Step 21"
},
{
"id": "657f4add33ea4b1f61ba3dc8",
"title": "Step 22"
}
],
"helpCategory": "Python"
}
@@ -0,0 +1,54 @@
---
id: 657e928716b77b2277980276
title: Step 1
challengeType: 20
dashedName: step-1
---
# --description--
In this project, you are going to learn about list comprehensions in Python by building a program that can take a `camelCase` or `PascalCase` formatted string and convert that to a `snake_case` formatted string.
List comprehensions in Python are a concise way to construct a list without using loops or the `.append()` method. Apart from being briefer, list comprehensions often run faster.
Start defining a new function named `convert_to_snake_case()` that accepts a string named `pascal_or_camel_cased_string` as input.
# --hints--
You should define a new function named `convert_to_snake_case()`. Don't forget the colon at the end and use `pass` to fill the function body.
```js
({
test: () => {
assert(__pyodide.runPython(`
import inspect
a = __locals.get("convert_to_snake_case")
inspect.isfunction(a)
`));
}
})
```
Your function should take a parameter named `pascal_or_camel_cased_string`.
```js
({
test: () => {
assert(__pyodide.runPython(`
import inspect
a = __locals.get('convert_to_snake_case')
'pascal_or_camel_cased_string' in inspect.signature(a).parameters
`));
}
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,39 @@
---
id: 657ed53c19461d4b95c4757a
title: Step 2
challengeType: 20
dashedName: step-2
---
# --description--
Now create a new list named `snake_cased_char_list` inside the function. You can use a set of empty square braces to create the new list.
This list will hold the characters of the string after you have converted them to snake case.
# --hints--
You should replace `pass` with an empty list named `snake_cased_char_list` within `convert_to_snake_case`.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list\s*=\s*\[\]/);
}
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
def convert_to_snake_case(pascal_or_camel_cased_string):
pass
--fcc-editable-region--
```
@@ -0,0 +1,39 @@
---
id: 657ee28cefc4945568287673
title: Step 3
challengeType: 20
dashedName: step-3
---
# --description--
Now that you have an empty list in place, you can start iterating through the input string and start converting each character to snake case.
Use a `for` loop to iterate through the `pascal_or_camel_cased_string`. Make sure to name the target variable `char` which is short for character.
# --hints--
You should write a new `for` loop with the target variable named `char`. Don't forget the colon at the end and to use `pass` to fill the loop body.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +for\s+char\s+in\s+pascal_or_camel_cased_string\s*:/);
}
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
--fcc-editable-region--
```
@@ -0,0 +1,41 @@
---
id: 657ef2a86d4e545cec9a85fb
title: Step 4
challengeType: 20
dashedName: step-4
---
# --description--
Uppercase characters in camel case or pascal case indicate the start of new words.
Inside the loop body, use an `if` statement in conjunction with the `.isupper()` string method to check for uppercase characters and move `pass` inside the new `if` statement.
# --hints--
You should write a new `if` statement with `char.isupper()` as the condition. Don't forget the colon at the end.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +if\s+char\.isupper\s*\(\s*\)\s*:/);
}
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
pass
--fcc-editable-region--
```
@@ -0,0 +1,48 @@
---
id: 657efa642593c5746acc5c81
title: Step 5
challengeType: 20
dashedName: step-5
---
# --description--
Inside the `if` statement body, you need to convert any uppercase character to lowercase and prepend an underscore to this lowercase character.
Use the `.lower()` string method to convert uppercase characters to lowercase characters. You can then concatenate an underscore to the character using the plus sign.
```python
'_' + char.lower()
```
Assign the modified character to a variable named `converted_character` inside the if statement body.
# --hints--
You should assign the modified character to a variable named `converted_character`.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +converted_character\s*=\s*("|')_\1\s*\+\s*char\.lower\s*\(\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
--fcc-editable-region--
if char.isupper():
pass
--fcc-editable-region--
```
@@ -0,0 +1,46 @@
---
id: 657efce98e958b75df86b305
title: Step 6
challengeType: 20
dashedName: step-6
---
# --description--
Still within the `if` statement body, use the `.append()` list method to add the converted character to the list you created earlier.
```py
snake_cased_char_list.append(converted_character)
```
The `.append()` method adds a given object to the end of the list you invoke it on.
# --hints--
You should use the `.append()` method to add the converted character to the `snake_cased_char_list`.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list\.append\s*\(\s*converted_character\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
--fcc-editable-region--
if char.isupper():
converted_character = '_' + char.lower()
--fcc-editable-region--
```
@@ -0,0 +1,55 @@
---
id: 657efdcf7fe23b76c0cff9ec
title: Step 7
challengeType: 20
dashedName: step-7
---
# --description--
Add an `else` clause on the same level as the existing `if` statement, inside the `for` loop. Add characters that are already in lowercase to the list of converted characters inside the body of the `else` clause.
# --hints--
You should add an `else` clause inside the `for` loop. Don't forget the colon at the end.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +else:/);
}
})
```
You should use the `.append()` method to add `char` to the `snake_cased_char_list` variable.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list.append\(char\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
--fcc-editable-region--
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
--fcc-editable-region--
```
@@ -0,0 +1,51 @@
---
id: 657effaa2a5e0277d71f9cbe
title: Step 8
challengeType: 20
dashedName: step-8
---
# --description--
By the end of the loop, `snake_cased_char_list` should contain all the converted characters in correct order. Use the `.join()` string method to convert the list of characters into a string.
```py
''.join(snake_cased_char_list)
```
This joins the characters from the list to the empty string on which you called the `.join()` method. Save the result in a variable named `snake_cased_string` on the same level as the `snake_cased_char_list` variable.
# --hints--
You should join the characters in the `snake_cased_char_list` list into a string using the `.join()` method and assign the string to a variable named `snake_cased_string` after your `for` loop.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_string\s*=\s*["']{2}\.join\s*\(\s*snake_cased_char_list\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,53 @@
---
id: 657f0044be09db790b1eb1c5
title: Step 9
challengeType: 20
dashedName: step-9
---
# --description--
Strings in camel case start with a capital character. Since you've converted all such characters to lowercase and prepended an underscore to them, chances are, the converted snake case string has a dangling underscode at the start.
The easiest way to strip such unwanted character is by using the `.strip()` string method and passing an underscore to the method as argument.
```py
snake_cased_string.strip('_')
```
Make sure to save the resulting string in a variable named `clean_snake_cased_string` on the same level as the `snake_cased_string` variable.
# --hints--
You should assign the resulting string from `snake_cased_string.strip('_')` to a variable named `clean_snake_cased_string`.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +clean_snake_cased_string\s*=\s*snake_cased_string.strip\(\s*("|')_\1\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
--fcc-editable-region--
snake_cased_string = ''.join(snake_cased_char_list)
--fcc-editable-region--
```
@@ -0,0 +1,47 @@
---
id: 657f01ae9aea647b27402d3e
title: Step 10
challengeType: 20
dashedName: step-10
---
# --description--
Now all that is left to complete this function is to return the `clean_snake_cased_string` from the function. So, go ahead and return the string by adding a `return` statement on the same level as the `clean_snake_cased_string` variable.
# --hints--
You should add `return clean_snake_cased_string` at the end of the `convert_to_snake_case` function.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +return\s+clean_snake_cased_string/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
snake_cased_string = ''.join(snake_cased_char_list)
clean_snake_cased_string = snake_cased_string.strip('_')
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,49 @@
---
id: 657f025ec86c3d7c4177b6be
title: Step 11
challengeType: 20
dashedName: step-11
---
# --description--
Since the function is now complete, put it to use inside another function. Create a new function called `main()` on the same level as the `convert_to_snake_case()` function.
# --hints--
You should define a new function named `main()`. Don't forget the colon at the end and use `pass` to fill the function body.
```js
({
test: () => {
assert(__pyodide.runPython(`
import inspect
a = __locals.get("main")
inspect.isfunction(a)
`));
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
snake_cased_string = ''.join(snake_cased_char_list)
clean_snake_cased_string = snake_cased_string.strip('_')
return clean_snake_cased_string
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,50 @@
---
id: 657f0353c9523d7d896873ea
title: Step 12
challengeType: 20
dashedName: step-12
---
# --description--
Inside the `main()` function, replace `pass` with a `convert_to_snake_case()` call. Pass the string `aLongAndComplexString` as input to the function and print out the output using the `print()` function.
# --hints--
You should call `convert_to_snake_case()` inside the `main()` function and pass `aLongAndComplexString` as input to the function.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const main = __helpers.python.getDef("\n" + transformedCode, "main");
const { function_body } = main;
assert.match(function_body, / +print\s*\(\s*convert_to_snake_case\s*\(\s*("|')aLongAndComplexString\1\s*\)\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
snake_cased_string = ''.join(snake_cased_char_list)
clean_snake_cased_string = snake_cased_string.strip('_')
return clean_snake_cased_string
--fcc-editable-region--
def main():
pass
--fcc-editable-region--
```
@@ -0,0 +1,48 @@
---
id: 657f04ed0035f47ed04d0f1f
title: Step 13
challengeType: 20
dashedName: step-13
---
# --description--
Before running the `main()` function, you need to make sure that the file is running as a script. Add an `if` statement on the same level as the two existing functions and check whether `__name__ == '__main__'` evaluates to `True` or not.
# --hints--
You should write a `if` clause to check whether `__name__ == '__main__'` evaluates to `True` or not. Don't forget the colon at the end and use `pass` to fill the `if` body.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
assert.match(transformedCode, /\nif\s+__name__\s*==\s*("|')__main__\1\s*:/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
snake_cased_string = ''.join(snake_cased_char_list)
clean_snake_cased_string = snake_cased_string.strip('_')
return clean_snake_cased_string
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
--fcc-editable-region--
```
@@ -0,0 +1,50 @@
---
id: 657f28a0482132aca51a9212
title: Step 14
challengeType: 20
dashedName: step-14
---
# --description--
Replace pass with a call to the `main()` function inside the body of the `if` statement. You should see the given camel or pascal cased string converted to snake case upon execution.
# --hints--
You should add a call to `main()` inside the `if` statement.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
assert.match(transformedCode, /\n +main\s*\(\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
snake_cased_string = ''.join(snake_cased_char_list)
clean_snake_cased_string = snake_cased_string.strip('_')
return clean_snake_cased_string
def main():
print(convert_to_snake_case('aLongAndComplexString'))
--fcc-editable-region--
if __name__ == '__main__':
pass
--fcc-editable-region--
```
@@ -0,0 +1,57 @@
---
id: 657f425dbab54e11993c80f0
title: Step 15
challengeType: 20
dashedName: step-15
---
# --description--
So far, in this project you have not seen any usage of list comprehensions whatsoever. Like you learned in the first step, list comprehensions are a more concise way of constructing lists in Python.
Begin the transition to comprehensions by commenting out all the lines of code inside the `convert_to_snake_case()` function. Don't delete them as they'll be helpful when you implement the logic using a list comprehension.
Remember to add the `pass` keyword to the function body to prevent the code from failing during the tests.
# --hints--
You should comment out all the 10 lines of code inside the `convert_to_snake_case()` function and nothing else. Add `pass` to fill temporarily the function body and avoid an error.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.equal(function_body.split("#").length - 1, 10);
}
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = []
for char in pascal_or_camel_cased_string:
if char.isupper():
converted_character = '_' + char.lower()
snake_cased_char_list.append(converted_character)
else:
snake_cased_char_list.append(char)
snake_cased_string = ''.join(snake_cased_char_list)
clean_snake_cased_string = snake_cased_string.strip('_')
return clean_snake_cased_string
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,58 @@
---
id: 657f4345abe7f2161f99f1ad
title: Step 16
challengeType: 20
dashedName: step-16
---
# --description--
Start by replacing `pass` with the variable `snake_cased_char_list` and assign it an empty list. Use the square brace notation to create the list but do not put anything between the braces.
Put the braces in separate lines so that you have some space between them, where you can work on the code for the list comprehension.
# --hints--
You should declare an empty list named `snake_cased_char_list` within `convert_to_snake_case`.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list\s*=\s*\[\n*\s*\n*\]/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
# snake_cased_char_list = []
# for char in pascal_or_camel_cased_string:
# if char.isupper():
# converted_character = '_' + char.lower()
# snake_cased_char_list.append(converted_character)
# else:
# snake_cased_char_list.append(char)
# snake_cased_string = ''.join(snake_cased_char_list)
# clean_snake_cased_string = snake_cased_string.strip('_')
# return clean_snake_cased_string
--fcc-editable-region--
pass
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,65 @@
---
id: 657f43d341a0dd17120cdb08
title: Step 17
challengeType: 20
dashedName: step-17
---
# --description--
Inside the space you left between the pair of square braces, you can describe the value that you would like to include in the list based on a given condition.
```py
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
]
```
Python will interpret this expression as "append `'_' + char.lower()` to the list if `char` is in uppercase" and this will convert the case for the capital letters in the input string.
Start by adding this line within the square braces.
# --hints--
You should add `'_' + char.lower() if char.isupper()` within the square braces of `snake_cased_char_list`.
```js
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list\s*=\s*\[\s*("|')_\1\s*\+\s*char\.lower\(\s*\)\s+if\s+char\.isupper\(\s*\)\s*\]/);
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
# snake_cased_char_list = []
# for char in pascal_or_camel_cased_string:
# if char.isupper():
# converted_character = '_' + char.lower()
# snake_cased_char_list.append(converted_character)
# else:
# snake_cased_char_list.append(char)
# snake_cased_string = ''.join(snake_cased_char_list)
# clean_snake_cased_string = snake_cased_string.strip('_')
# return clean_snake_cased_string
--fcc-editable-region--
snake_cased_char_list = [
]
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,67 @@
---
id: 657f456223b8c1187b461987
title: Step 18
challengeType: 20
dashedName: step-18
---
# --description--
When you start a list comprehension with an `if` statement like this, Python requires you to also add an `else` clause to the expression.
```py
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
]
```
Python will interpret this updated expression as "append `'_' + char.lower()` to the list if `char` is in uppercase, append `char` as is otherwise" and this covers the case for both the capital and lowercase letters in the input string.
Add an `else` clause inside the pair of square braces.
# --hints--
You should add `else char` after `'_' + char.lower() if char.isupper()` within the square braces of `snake_cased_char_list`.
```js
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list\s*=\s*\[\s*("|')_\1\s*\+\s*char\.lower\(\s*\)\s+if\s+char\.isupper\(\s*\)\s*else\s+char\s*\]/);
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
# snake_cased_char_list = []
# for char in pascal_or_camel_cased_string:
# if char.isupper():
# converted_character = '_' + char.lower()
# snake_cased_char_list.append(converted_character)
# else:
# snake_cased_char_list.append(char)
# snake_cased_string = ''.join(snake_cased_char_list)
# clean_snake_cased_string = snake_cased_string.strip('_')
# return clean_snake_cased_string
--fcc-editable-region--
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
]
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,75 @@
---
id: 657f465f8e718b19c5105ae5
title: Step 19
challengeType: 20
dashedName: step-19
---
# --description--
The final piece of the puzzle is the input string itself. The list comprehension needs to know about the object it'll iterate upon.
In this case, you need to iterate upon all the characters of the string.
```py
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
for char in pascal_or_camel_cased_string
]
```
And there you have it. These three lines of code do the same task as the `for` loop you worked on previously while being cleaner and somewhat faster.
Add this last line of code to iterate over the characters of the string in your list comprehension and make sure that you're writing it within the pair of square braces.
# --hints--
You should add `for char in pascal_or_camel_cased_string` after `else char` within the square braces of `snake_cased_char_list`.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +snake_cased_char_list\s*=\s*\[\s*'_'\s*\+\s*char\.lower\(\s*\)\s+if\s+char\.isupper\(\s*\)\s*else\s*char\s*for\s+char\s+in\s+pascal_or_camel_cased_string\s*\]/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
# snake_cased_char_list = []
# for char in pascal_or_camel_cased_string:
# if char.isupper():
# converted_character = '_' + char.lower()
# snake_cased_char_list.append(converted_character)
# else:
# snake_cased_char_list.append(char)
# snake_cased_string = ''.join(snake_cased_char_list)
# clean_snake_cased_string = snake_cased_string.strip('_')
# return clean_snake_cased_string
--fcc-editable-region--
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
]
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,68 @@
---
id: 657f47b12c51e41b3149e584
title: Step 20
challengeType: 20
dashedName: step-20
---
# --description--
You will still need to join the list elements into a string, strip off any dangling underscores and return the string. Even though you can do that like you did earlier, let's see a shorter alternative.
```py
return ''.join(snake_cased_char_list).strip('_')
```
This single line of code will join the list of characters into a string, strip off any dangling underscores, and return the resulting string. Add this line on the same level as the `snake_cased_char_list` variable and inside the `convert_to_snake_case()` function.
# --hints--
You should return `''.join(snake_cased_char_list).strip('_')` at the end of `convert_to_snake_case()` function.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.match(function_body, / +return\s+["']{2}\.join\(\s*snake_cased_char_list\s*\)\.strip\(\s*("|')_\1\s*\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
# snake_cased_char_list = []
# for char in pascal_or_camel_cased_string:
# if char.isupper():
# converted_character = '_' + char.lower()
# snake_cased_char_list.append(converted_character)
# else:
# snake_cased_char_list.append(char)
# snake_cased_string = ''.join(snake_cased_char_list)
# clean_snake_cased_string = snake_cased_string.strip('_')
# return clean_snake_cased_string
--fcc-editable-region--
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
for char in pascal_or_camel_cased_string
]
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,61 @@
---
id: 657f4a4a5828a01de04b652f
title: Step 21
challengeType: 20
dashedName: step-21
---
# --description--
Get rid of the commented lines of code inside the `convert_to_snake_case()` function to clean up the function definition.
# --hints--
You should not have any commented line of code in the `convert_to_snake_case()` function at all.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const convert_to_snake_case = __helpers.python.getDef("\n" + transformedCode, "convert_to_snake_case");
const { function_body } = convert_to_snake_case;
assert.equal(function_body.split("#").length - 1, 0);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
--fcc-editable-region--
# snake_cased_char_list = []
# for char in pascal_or_camel_cased_string:
# if char.isupper():
# converted_character = '_' + char.lower()
# snake_cased_char_list.append(converted_character)
# else:
# snake_cased_char_list.append(char)
# snake_cased_string = ''.join(snake_cased_char_list)
# clean_snake_cased_string = snake_cased_string.strip('_')
# return clean_snake_cased_string
--fcc-editable-region--
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
for char in pascal_or_camel_cased_string
]
return ''.join(snake_cased_char_list).strip('_')
def main():
print(convert_to_snake_case('aLongAndComplexString'))
if __name__ == '__main__':
main()
```
@@ -0,0 +1,78 @@
---
id: 657f4add33ea4b1f61ba3dc8
title: Step 22
challengeType: 20
dashedName: step-22
---
# --description--
Finally try out this new implementation by executing the program. Change the input string to `IAmAPascalCasedString` and see if it comes out as `i_am_a_pascal_cased_string`, even though that's a lie.
If you've done everything correctly, you should see the input string converted into snake case, like before.
Congratulations! Now your `convert_to_snake_case()` function is ready.
# --hints--
You should change the input string from `aLongAndComplexString` to `IAmAPascalCasedString` inside the `main()` function.
```js
({
test: () => {
const transformedCode = code.replace(/\r/g, "");
const main = __helpers.python.getDef("\n" + transformedCode, "main");
const { function_body } = main;
assert.match(function_body, / +print\(convert_to_snake_case\('IAmAPascalCasedString'\)\)/);
}
})
```
# --seed--
## --seed-contents--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
for char in pascal_or_camel_cased_string
]
return ''.join(snake_cased_char_list).strip('_')
--fcc-editable-region--
def main():
print(convert_to_snake_case('aLongAndComplexString'))
--fcc-editable-region--
if __name__ == '__main__':
main()
```
# --solutions--
```py
def convert_to_snake_case(pascal_or_camel_cased_string):
snake_cased_char_list = [
'_' + char.lower() if char.isupper()
else char
for char in pascal_or_camel_cased_string
]
return ''.join(snake_cased_char_list).strip('_')
def main():
print(convert_to_snake_case('IAmAPascalCasedString'))
if __name__ == '__main__':
main()
```