Skip to content

Commit 2fe2548

Browse files
committed
add more details about performance and complexity to strings
1 parent 2564014 commit 2fe2548

File tree

2 files changed

+79
-8
lines changed

2 files changed

+79
-8
lines changed

array/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ To provide a real-world analogy, consider an array of athletes preparing for a s
66

77
## Implementation
88

9-
In the Go programming language, arrays are considered values rather than pointers and represent the entirety of the array. Whenever an array is passed to a function, a copy is created, resulting in additional memory usage. To avoid this, it is possible to pass a pointer to an array, or use slices instead. The size of the array is constant and it must be known at compile time, and there is no need to use the built-in `make` function when defining arrays.
9+
In the Go programming language, (arrays)[https://go.dev/blog/slices] are considered values rather than pointers and represent the entirety of the array. Whenever an array is passed to a function, a copy is created, resulting in additional memory usage. To avoid this, it is possible to pass a pointer to an array, or use slices instead. The size of the array is constant and it must be known at compile time, and there is no need to use the built-in `make` function when defining arrays.
1010

1111
```Go
1212
package main

strings/README.md

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# String
22

3-
A string is a ubiquitous data structure, typically a built-in data type in programming languages. However, beneath the surface, strings are essentially arrays of characters that enable textual data storage and manipulation.
3+
A string is a ubiquitous data structure, typically a built-in data type in programming languages. However, beneath the surface, strings are essentially [slices](../array/) of characters that enable textual data storage and manipulation.
44

55
## Implementation
66

7-
In Go, strings are a data type. Behind the scenes strings are a slice of bytes. The `strings` package provides several useful convenience functions. Examples include:
7+
In Go, [strings](https://go.dev/blog/strings) are a data type. Behind the scenes strings are an immutable slice of bytes. Since Go is a UTF-8 compliant language, each character in Go can take up to 4 bytes of storage.
8+
9+
The `strings` package provides several useful convenience functions. Examples include:
810

911
* [Index](https://golang.org/pkg/strings/#Index), [Contains](https://golang.org/pkg/strings/#Contains), [HasPrefix](https://golang.org/pkg/strings/#HasPrefix), [HasSuffix](https://golang.org/pkg/strings/#HasSuffix)
1012
* [Split](https://golang.org/pkg/strings/#Split), [Fields](https://golang.org/pkg/strings/#Split), [Join](https://golang.org/pkg/strings/#Join)
@@ -13,27 +15,96 @@ In Go, strings are a data type. Behind the scenes strings are a slice of bytes.
1315
* [Title](https://golang.org/pkg/strings/#Title), [ToLower](https://golang.org/pkg/strings/#ToLower), [ToUpper](https://golang.org/pkg/strings/#ToUpper)
1416
* [Trim](https://golang.org/pkg/strings/#Trim), [TrimSpace](https://golang.org/pkg/strings/#TrimSpace), [TrimSuffix](https://golang.org/pkg/strings/#TrimSuffix), [TrimPrefix](https://golang.org/pkg/strings/#TrimPrefix)
1517

16-
When a string is iterated in Go using the `range` keyword, every element becomes a [rune](https://blog.golang.org/strings#TOC_5.) which is an alias for the type `int32`. If the code being written works with many single-character strings, it is better to define variables and function parameters as `rune`. The following code shows how to iterate through a string.
18+
When a iterating every character in a string in Go using the `range` keyword, every element becomes a [rune](https://blog.golang.org/strings#TOC_5.) which is an alias for the type `int32`. If the code being written works with many single-character strings, it is better to define variables and function parameters as `rune` rather than convert them many times. The following code shows how to iterate through a string.
19+
20+
```Go
21+
package main
22+
23+
import "fmt"
24+
25+
/*
26+
main outputs the rune (int32) value of each character:
27+
28+
Char #0 "a" has value 97
29+
Char #1 "A" has value 65
30+
Char #2 "和" has value 21644
31+
Char #5 "平" has value 24179
32+
Char #8 "😊" has value 128522
33+
*/
34+
func main() {
35+
for i, r := range "aA𓅚😊" {
36+
fmt.Printf("Char #%d %q has value %d\n", i, string(r), r)
37+
}
38+
}
39+
```
40+
41+
A very common tool to use for manipulating strings in Go is the `fmt.Sprtinf` function. This is specially useful when converting many values into a string.
1742

1843
```Go
1944
package main
2045

46+
import "fmt"
47+
48+
func main() {
49+
number := 1
50+
value := 1.1
51+
name := "foo"
52+
53+
output := fmt.Sprintf("%d %f %s", number, value, name)
54+
fmt.Println(output) // 1 1.100000 foo
55+
}
56+
```
57+
58+
### Regular Expressions
59+
60+
Unlike many other programming languages, in Go [regular expressions](https://golang.org/pkg/regexp/) are [guaranteed](https://swtch.com/~rsc/regexp/regexp1.html) to have O(n) time complexity where n is the length of the input, making them a viable and practical option for pattern matching in a string.
61+
62+
Here is an example of how you can find a pattern using regular expressions in Go. Given a string return the string if it contains a fish word. A fish word is a word that starts with `fi` optionally followed by other character(s) and ends with `sh`. Examples include {`fish`, `finish`}.
63+
64+
```GO
65+
package main
66+
2167
import (
2268
"fmt"
69+
"regexp"
2370
)
2471

72+
var fishPattern = regexp.MustCompile(`(?i).*fi\w*sh\b`)
73+
74+
// main outputs [selfish][shellfish][fish][finish][Finnish]
2575
func main() {
26-
for i, r := range "abcd" {
27-
fmt.Printf("Char #%d %q has value %d\n", i, string(r), r)
76+
inputs := []string{"shift", "selfish", "shellfish", "fish dish", "finish", "Finnish"}
77+
78+
for _, input := range inputs {
79+
matches := fishPattern.FindAllString(input, -1)
80+
if len(matches) > 0 {
81+
fmt.Print(matches)
82+
}
2883
}
2984
}
3085
```
3186

3287
## Complexity
3388

34-
Strings have the same complexity as [arrays](../array/) and slices in Go.
89+
Since strings are slices of bytes, the time complexity of string operations should be similar to [arrays](../array/). Reading a character at a given index is O(1), but since strings are immutable modifying them involves creating a new string making it a O(n) operation. Go standard library includes `strings.Builder` for more efficient string building.
90+
91+
The space complexity to store a string depends on the type of characters. This following example shows how we can index a string and print the hexadecimal value of every byte in it.
92+
93+
```GO
94+
package main
95+
96+
import "fmt"
97+
98+
// main Outputs 41 f0 93 85 9a f0 9f 98 8a.
99+
func main() {
100+
input := "A𓅚😊"
101+
for i := 0; i < len(input); i++ {
102+
fmt.Printf("%x ", input[i])
103+
}
104+
}
105+
```
35106

36-
Unlike many other programming languages, [regular expressions](https://golang.org/pkg/regexp/) are guaranteed to have O(n) time complexity in Go, allowing efficient string pattern matching.
107+
The output of the above code indicates that 9 bytes are used to store the 3 input characters. 1 byte for the first character and 4 bytes for each of the remaining two.
37108

38109
## Application
39110

0 commit comments

Comments
 (0)