You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b91f9ef
Browse filesBrowse the repository at this point in the historyBrowse files
[Acronym] Add new approach and update performance article (#4203)
* fix benchmark & add timings for new approach
* update "measurements were taken on" part
* improve performance article
* fix the performance article's `config.json`
* add approach docs for new approach
* Apply suggestions from code review
Co-authored-by: BethanyG <BethanyG@users.noreply.github.com>
* minor fixes
---------
Co-authored-by: BethanyG <BethanyG@users.noreply.github.com>
# Using a `generator-expression` for both cleaning and joining
2
+
3
+
```python
4
+
from string import ascii_letters
5
+
6
+
7
+
VALID_CHARS= {'', '-'} |set(ascii_letters)
8
+
9
+
10
+
defabbreviate(to_abbreviate):
11
+
to_abbreviate =''.join(''if char =='-'else char
12
+
for char in to_abbreviate
13
+
if char inVALID_CHARS)
14
+
15
+
return''.join(word[0] for word in to_abbreviate.split()).upper()
16
+
```
17
+
18
+
One way someone might try to increase performce is to use a single [generator expression][generator-expression] to clean the input, rather than using multiple calls to [`str.replace()`][str-replace].
19
+
However, this approach is actually amongst the slower ones.
20
+
(See the [performance article][article-performance] for more detail.)
21
+
22
+
In this approach, the `VALID_CHARS` constant is first defined using `string.ascii_letters`, a space, and a hyphen.
23
+
In `abbreviate()`, the first generator expression iterates over `to_abbreviate`, excluding any code points that are not a member of the `VALID_CHARS` set.
24
+
For each code point that is not excluded, the expression passes it into [`str.join()`][str-join] (unless it is a hyphen, in which case it replaces the hyphen with a space).
25
+
`to_abbreviate` is then set to the result of the `str.join()`, preparing it for the next step.
26
+
27
+
Next, [`to_abbreviate.split()`][str-split] is used to split `to_abbreviate` into words separated by whitespace — we can ignore the case of hyphens as we already replaced all of them with spaces.
28
+
Now the second generator expression iterates over the list returned by `to_abbreviate.split()`, yeilding the first code point in each word.
29
+
These code points are passed to another `str.join()`, which is then [chained][chaining] to [`str.upper()`][str-upper].
30
+
Now that both steps are complete, we return the result of `str.upper()` directly on the same line.
For more information, check out the [list-comprehension][approach-list-comprehension]approach or the [generator-expression][approach-generator-expression] approach.
71
+
For more information, check out the [list-comprehension][approach-list-comprehension] approach or the [generator-expression][approach-generator-expression] approach.
73
72
74
73
75
74
## Approach: scrub with `replace()` and join via `map()`
return''.join(word[0] for word in removed).upper()
112
111
```
@@ -120,36 +119,57 @@ For more information, take a look at the [regex-join][approach-regex-join] appro
120
119
import re
121
120
122
121
123
-
defabbreviate_regex_sub(to_abbreviate):
122
+
defabbreviate(to_abbreviate):
124
123
pattern = re.compile(r"(?<!_)\B[\w']+|[ ,\-_]")
125
124
126
-
returnre.sub(pattern, "", to_abbreviate.upper())
125
+
return re.sub(pattern, "", to_abbreviate.upper())
127
126
```
128
127
129
128
For more information, read the [regex-sub][approach-regex-sub] approach.
130
129
131
130
131
+
## Approach: use a `generator-expression` for both cleaning and joining
132
+
133
+
```python
134
+
from string import ascii_letters
135
+
136
+
137
+
VALID_CHARS= {'', '-'} |set(ascii_letters)
138
+
139
+
140
+
defabbreviate(to_abbreviate):
141
+
to_abbreviate =''.join(''if char =='-'else char
142
+
for char in to_abbreviate
143
+
if char inVALID_CHARS)
144
+
145
+
return''.join(word[0] for word in to_abbreviate.split()).upper()
146
+
```
147
+
148
+
For more information, take a look at the [double `generator-expression` approach][approach-double-generator-expression].
149
+
150
+
132
151
## Other approaches
133
152
134
-
Besides these seven idiomatic approaches, there are a multitude of possible variations using different string cleaning and joining methods.
153
+
Besides these eight idiomatic approaches, there are a multitude of possible variations using different string cleaning and joining methods.
135
154
136
155
However, these listed approaches cover the majority of 'mainstream' strategies.
137
156
138
157
139
158
## Which approach to use?
140
159
141
-
All seven approaches are idiomatic, and show multiple paradigms and possibilities.
160
+
All eight approaches are idiomatic, and show multiple paradigms and possibilities.
142
161
All approaches are also `O(n)`, with `n` being the length of the input string.
143
162
No matter the removal method, the entire input string must be iterated through to be cleaned and the first letters extracted.
144
163
145
-
Of these strategies, the `loop` approach is the fastest, although `list-comprehension`, `map`, and `reduce` have near-identical performance for the test data.
164
+
Of these strategies, the `loop` approach is the fastest, although `list-comprehension`, `map`, and `reduce` have near-identical performance for the test data.
146
165
All approaches are fairly succinct and readable, although the 'classic' loop is probably the easiest understood by those coming to Python from other programming languages.
147
166
148
167
149
-
The least performant for the test data was using a `generator-expression`, `re.findall` and `re.sub` (_least performant_).
168
+
The least performant for the test data was using `generator-expression`s (both one and two), `re.findall`, and `re.sub`.
150
169
151
170
To compare performance of the approaches, take a look at the [Performance article][article-performance].
0 commit comments