{"id":"strings-and-lists-count-index-replace","slug":"count-and-replace","title":"count, index and replace","text":"Strings and lists have more methods worth knowing. **`count`** tells how many times something appears. It works on strings, where it counts a piece of text, and on lists, where it counts an item:\n\n```python\ntext = \"this list has six items\"\nprint(text.count(\"s\"))\nprint(text.count(\"is\"))\nnumbers = [3, 1, 3, 3, 2]\nprint(numbers.count(3))\nprint(\"banana\".count(\"ana\"))\n```\n\n```output\n5\n2\n3\n1\n```\n\nThe last line needs a closer look. `ana` starts at index 1 of `banana` and again at index 3, but the two share the `a` in the middle. `count` doesn't count pieces that overlap: once it has found one, it goes on looking only after its end, so it finds just one.\n\n### Where is it?\n\n**`index`** returns the index of the first place where something is found, in a string or in a list:\n\n```python\nnames = [\"Ada\", \"Linus\", \"Grace\"]\nprint(names.index(\"Grace\"))\nprint(\"banana\".index(\"an\"))\nprint(names.index(\"Guido\"))\n```\n\n```output\n2\n1\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 4, in <module>\n    print(names.index(\"Guido\"))\n          ~~~~~~~~~~~^^^^^^^^^\nValueError: list.index(x): x not in list\n```\n\nIf the item isn't there, `index` stops the program, so check with `in` first. For strings, you also know `find`, which returns -1 instead of stopping.\n\n### Replacing\n\n**`replace`** returns a new string where every appearance of one piece of text is replaced with another:\n\n```python\ntext = \"I like cats. Cats like me.\"\nprint(text.replace(\"like\", \"love\"))\nprint(text.replace(\"cat\", \"dog\"))\nprint(text)\n```\n\n```output\nI love cats. Cats love me.\nI like dogs. Cats like me.\nI like cats. Cats like me.\n```\n\nIt replaces every appearance, not just the first. Capital letters count: `\"Cats\"` isn't `\"cat\"`, so it stays. And since strings can't be changed, `text` itself stays as it was. Forgetting that is the most common `replace` bug:\n\n```python\ntext = \"Hello, World\"\ntext.replace(\"World\", \"Python\")\nprint(text)\ntext = text.replace(\"World\", \"Python\")\nprint(text)\n```\n\n```output\nHello, World\nHello, Python\n```\n\nThe first `replace` makes the new string and throws it away. Only when the result is stored does `text` say `Hello, Python`.\n\nReplacing with the empty string `\"\"` removes a piece of text: `\"1,000,000\".replace(\",\", \"\")` is `\"1000000\"`.\n","task":"Fill in the blanks so the program counts the letter `e` in the text and then replaces every `cat` with `dog`:\n\n```\nLetter e: 4\nthe dog sees the dog\n```\n","kind":"fill","seed":"text = \"the cat sees the cat\"\nprint(\"Letter e:\", text.[[count]](\"e\"))\ntext = text.[[replace]](\"cat\", \"dog\")\nprint(text)\n","solution":"text = \"the cat sees the cat\"\nprint(\"Letter e:\", text.count(\"e\"))\ntext = text.replace(\"cat\", \"dog\")\nprint(text)\n","hints":["One method counts how many times a piece of text appears, the other replaces it with another.","`count(\"e\")` counts the letter e, and `replace(\"cat\", \"dog\")` returns the text with every cat replaced."],"tests":[{"name":"Output","stdin":"","expect":"Letter e: 4\nthe dog sees the dog","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Write the function `censor(text: str, banned: list) -> str`, which returns the text with every banned word replaced by stars, one star per letter. For example, `censor(\"you silly goose\", [\"silly\"])` returns `'you ***** goose'`.\n","kind":"code","seed":"def censor(text: str, banned: list) -> str:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(censor(\"you silly goose\", [\"silly\"]))\n","solution":"def censor(text: str, banned: list) -> str:\n    for word in banned:\n        text = text.replace(word, \"*\" * len(word))\n    return text\n\n\nif __name__ == \"__main__\":\n    print(censor(\"you silly goose\", [\"silly\"]))\n","hints":["Go through the banned words with a `for` loop and replace each of them in the text.","The stars for a word are `\"*\" * len(word)`.","`replace` returns a new string, so store it: `text = text.replace(word, \"*\" * len(word))`. Return `text` after the loop."],"tests":[{"name":"censor(\"you silly goose\", [\"silly\"])","stdin":"","call":"censor(\"you silly goose\", [\"silly\"])\n","expect":"'you ***** goose'","hidden":false,"returns":true},{"name":"censor(\"darn it, darn this darn bug\", [\"darn\", \"bug\"])","stdin":"","call":"censor(\"darn it, darn this darn bug\", [\"darn\", \"bug\"])\n","expect":"'**** it, **** this **** ***'","hidden":true,"returns":true},{"name":"censor(\"all is fine\", [\"bad\"])","stdin":"","call":"censor(\"all is fine\", [\"bad\"])\n","expect":"'all is fine'","hidden":true,"returns":true}],"require":[],"forbid":[]},{"task":"Write a program that asks for a text and a piece of text to look for. It prints how many times the piece is in the text and the index where it's first found. If it isn't found at all, it prints `Not found`:\n\n```\nText: the cat sat on the mat\nFind: at\nFound 3 times, first at index 5\n```\n","kind":"code","seed":"# Count and find a piece of text.\n","solution":"# Count and find a piece of text.\ntext = input(\"Text: \")\npiece = input(\"Find: \")\nif piece in text:\n    count = text.count(piece)\n    first = text.index(piece)\n    print(f\"Found {count} times, first at index {first}\")\nelse:\n    print(\"Not found\")\n","hints":["Check with `if piece in text:` first, because `index` stops the program when the piece isn't there.","`text.count(piece)` gives the number of times and `text.index(piece)` the first index.","Store both numbers in variables, such as `count` and `first`, and put them in the line with an f-string: `f\"Found {count} times, first at index {first}\"`."],"tests":[{"name":"Test 1","stdin":"the cat sat on the mat\nat\n","expect":"Text: the cat sat on the mat\nFind: at\nFound 3 times, first at index 5","hidden":false},{"name":"Test 2","stdin":"banana\nna\n","expect":"Text: banana\nFind: na\nFound 2 times, first at index 2","hidden":true},{"name":"Test 3","stdin":"hello\nx\n","expect":"Text: hello\nFind: x\nNot found","hidden":true}],"require":[],"forbid":[]}]}