From 36b6a788332ec9b14ff702d178496ef78326467c Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Wed, 14 Feb 2024 01:14:52 +0100 Subject: [PATCH] strings --- strings/string_manipulation/README.md | 88 +++++++++++++++++++ .../string_manipulation/solution/strings.py | 43 +++++---- strings/string_manipulation/strings.py | 48 +++++++++- strings/string_manipulation/test_strings.py | 29 +++--- 4 files changed, 171 insertions(+), 37 deletions(-) diff --git a/strings/string_manipulation/README.md b/strings/string_manipulation/README.md index 6e0787d..b129e91 100644 --- a/strings/string_manipulation/README.md +++ b/strings/string_manipulation/README.md @@ -2,3 +2,91 @@ Diese Teilaufgaben sind teilweise sehr einfach zu implementieren und sollen veranschaulichen was man alles mit Strings machen kann. Hierbei könnt ihr euch es natürlich einfach machen und die Buildins von `str` verwenden oder die Funktionen komplett selber implementieren. +## String-Class + +Zunächst möchten wir eine *dataclass* *String* erstellen die genau einen *str* als Argument nimmt und in eimem privaten Attribut *__s* speichert. Dieses Attribut soll auch von Typ *str* sein und unsere *String* klasse intern representieren. + +## Operatoren, Str, Len, und Iterator + +Nun möchten wir alle standard Operatoren und Funktionen für unseren *String* überschreiben + +### `__str__` + +Diese Methode soll einfach die *str* Representation unserer *String* Klasse sein + +### `__add__`, `__radd__` + +Diese Methode soll unseren *String* nicht verändern, aber zwei *Str* konkatenieren. Hierbei kann ein *Str* sowohl ein *String* als auch ein *str* sein! Hierbei wird `self` mit `other` konkateniert. + +`__radd__` hat genau das selbe verhalten, nur dass `other` mit `self` konkateniert wird. + +```python +my_string = String("hello") +assert str(my_string + " world") == "hello world" +assert str("world " + my_str) == "world hello" +``` + +### `__len__` + +Diese Methode soll uns die Länge unseres Strings zurückgeben + +```python +assert len(String("hello world")) == 11 +``` + +### `__eq__` + +Diese Methode soll die Vergleichbarkeit zwischen *str* und *String* implementieren, also + +```python +my_string = String("hello") +assert my_string == "hello" +assert my_string == String("hello") +``` + +### `__iter__` + +Diese Methode soll einen Iterator aus unserem *String* machen damit wir über die einzelnen Characters iterieren können + +```python +my_string = String("hello world") +my_it = iter(my_string) +for c in my_it: + print(c, end="") # hello world +``` + +## `concat` + +Hierbei soll *self* nicht verändert werden, wir möchten *self* mit *other* konkatenieren und einen neuen konkatenierten *String* zurückgeben + +## `contains` + +Wir möchten schauen ob *other* in *self* enthalten ist + +## `substring` + +Wir möchten einen neuen *String* zurückgeben der alle Stellen von `start` bis `end`enthält. Hierbei sollten man von ausgehen dass `start` und `end` nicht negativ oder größer als der String sind. + +## `strip` + +Wir möchten am Anfang und Ende des Strings alle Stellen entfernen, solang diese in `chars` enthalten sind. Also + +```python +assert String(" hello ").strip() == "hello" +``` + +## `replace` + +Diese Methode soll überall `old` mit `new` genau `count`-Mal ersetzen. Wenn `count` negativ ist soll einfach jedes `old` ersetzt werden. + +## `add_prefix`, `add_suffix` + +`add_prefix` soll einen Prefix zu unserem String konkatenieren und analog dazu soll `add_suffix` einen Suffix zu unserem String konkatenieren + +## `join` + +Diese soll eine iterierbare Datenstruktur nehmen und zwischen jedes Element unseren *String* konkatenieren. Wir können davon ausgehen dass `T` zu einem *str* konvertiert werden kann (also `str(T)` anwendbar ist) + +```python +assert String(", ").join([1, 2, 3, 4, 5]) == "1, 2, 3, 4, 5" +``` \ No newline at end of file diff --git a/strings/string_manipulation/solution/strings.py b/strings/string_manipulation/solution/strings.py index 1847756..d29c49c 100644 --- a/strings/string_manipulation/solution/strings.py +++ b/strings/string_manipulation/solution/strings.py @@ -15,18 +15,24 @@ class String: def __add__(self, other: Str) -> 'String': return String(self.__s + str(other)) - - def __iadd__(self, other: Str) -> 'String': - return self + other + def __radd__(self, other: Str) -> 'String': + return String(str(other) + self.__s) + def __len__(self) -> int: return len(self.__s) def __eq__(self, other: Str) -> bool: return str(self) == str(other) + + def __iter__(self) -> Iterator[chr]: + pass + for i in range(0, len(self)): + yield chr(self.__s[i]) + raise StopIteration - def concat(self, other: Str) -> None: - self + other + def concat(self, other: Str) -> 'String': + return self + other def contains(self, other: Str) -> bool: s = str(other) @@ -38,9 +44,6 @@ class String: else: s = str(other) return len(s) == 0 - - def concat(self, other: Str) -> None: - self.__s += str(other) def substring(self, start: int, end: int) -> 'String': substr: str = "" @@ -49,39 +52,41 @@ class String: substr += c return substr - def strip(self, chars: Str = ' ' + '\n' + '\t' + '\r') -> None: + def strip(self, chars: Str = ' ' + '\n' + '\t' + '\r') -> 'String': i = 0 while i < len(self) and self.__s[i] in chars: i += 1 j: int = len(self) - 1 while i <= j and self.__s[j] in chars: j -= 1 - self.__s: str = str(self)[i:j + 1] + return String(str(self)[i:j + 1]) - def replace(self, old: Str, new: Str, count = -1) -> None: + def replace(self, old: Str, new: Str, count = -1) -> 'String': o = str(old) n = str(new) + new_str = self.__s j = 0 - while count > 0 or (count < 0 and j < len(self)): + while count > 0 or (count < 0 and j < len(new_str)): i: int = j - while len(o) > 0 and j < len(self): - if o[0] == self.__s[j]: + while len(o) > 0 and j < len(new_str): + if o[0] == new_str[j]: o: str = o[1:] j += 1 else: j += 1 break if len(o) <= 0: - self.__s = self.__s[:i] + n + self.__s[j:] + new_str = new_str[:i] + n + new_str[j:] j += len(new) - len(old) count -= 1 o = str(old) + return new_str - def add_prefix(self, prefix: Str) -> None: - self.__s = str(prefix) + self.__s + def add_prefix(self, prefix: Str) -> 'String': + return prefix + self - def add_suffix(self, suffix: Str) -> None: - self.__s += str(suffix) + def add_suffix(self, suffix: Str) -> 'String': + return self + suffix def join[T](self, xs: Iterator[T]) -> 'String': output = String("") diff --git a/strings/string_manipulation/strings.py b/strings/string_manipulation/strings.py index 826195f..11df936 100644 --- a/strings/string_manipulation/strings.py +++ b/strings/string_manipulation/strings.py @@ -1,9 +1,53 @@ from dataclasses import dataclass +from typing import Iterator # kleine Hilfestellung mit `Str` kann man sowohl `str` als auch `String` meinen type Str = 'String' | str @dataclass class String: - # Implement! - pass \ No newline at end of file + + def __post_init__(self, s: str) -> None: + pass + + def __str__(self) -> str: + pass + + def __add__(self, other: Str) -> 'String': + pass + + def __radd__(self, other: Str) -> 'String': + pass + + def __len__(self, other: Str) -> int: + pass + + def __eq__(self, other: Str) -> bool: + pass + + def __iter__(self) -> Iterator[chr]: + pass + + def concat(self, other: Str) -> 'String': + pass + + def contains(self, other: Str) -> bool: + pass + + def substring(self, start: int, end: int) -> 'String': + pass + + def strip(self, chars: Str = ' ' + '\n' + '\t' + '\r') -> 'String': + pass + + def replace(self, old: Str, new: Str, count = -1) -> 'String': + pass + + def add_prefix(self, prefix: Str) -> 'String': + pass + + def add_suffix(self, suffix: Str) -> 'String': + pass + + def join[T](self, xs: Iterator[T]) -> 'String': + pass \ No newline at end of file diff --git a/strings/string_manipulation/test_strings.py b/strings/string_manipulation/test_strings.py index d8688ee..febd07b 100644 --- a/strings/string_manipulation/test_strings.py +++ b/strings/string_manipulation/test_strings.py @@ -13,36 +13,33 @@ def test_strings_concat(): test_str = String("") test_str += "test succesful!" assert test_str == "test succesful!" - test_str.concat(" Or is it?") - assert test_str == "test succesful! Or is it?" + assert test_str.concat(" Or is it?") == "test succesful! Or is it?" def test_strings_strip(): test_str = String(" halo? \n") - test_str.strip() + test_str = test_str.strip() assert test_str == "halo?" test_str = String(" \n ") - test_str.strip() + test_str = test_str.strip() assert test_str == "" def test_strings_replace(): test_str = String("har har har, try replacing thhis") - test_str.replace('har ', 'ha') - assert test_str == "hahahar, try replacing thhis" - test_str.replace('r', '', 1) - assert test_str == "hahaha, try replacing thhis" - test_str.replace('hh', 'h') - assert test_str == "hahaha, try replacing this" - test_str.replace('try replacing this', "replaced") - assert test_str == "hahaha, replaced" + assert test_str.replace('har ', 'ha') == "hahahar, try replacing thhis" + test_str = test_str.replace('har ', 'ha') + assert test_str.replace('r', '', 1) == "hahaha, try replacing thhis" + test_str = test_str.replace('r', '', 1) + assert test_str.replace('hh', 'h') == "hahaha, try replacing this" + test_str = test_str.replace('hh', 'h') + assert test_str.replace('try replacing this', "replaced") == "hahaha, replaced" def test_add_pre_suf(): test_str = String(" ") - test_str.add_suffix("suff") - assert test_str == " suff" - test_str.add_prefix("pref") - assert test_str == "pref suff" + assert test_str.add_suffix("suff") == " suff" + assert test_str.add_prefix("pref") == "pref " + assert test_str.add_suffix("suff").add_prefix("pref") == "pref suff" def test_join(): assert String(", ").join([1, 2, 3, 4]) == "1, 2, 3, 4"