Dynamic arrays give O(1) indexing and amortized O(1) append; inserting or deleting in the middle shifts elements and is O(n). Slices and strings differ sharply by language: know when you copied data and when you only made a view.
| Python | Go | TypeScript | C++ | |
|---|---|---|---|---|
| create O(n) | a = [1, 2, 3] | a := []int{1, 2, 3} | const a = [1, 2, 3] | vector<int> a{1, 2, 3}; |
| length O(1) | len(a) | len(a) | a.length | a.size() |
| index O(1) | x = a[i] / a[-1] | x := a[i] | const x = a[i] | int x = a[i]; |
| update O(1) | a[i] = x | a[i] = x | a[i] = x | a[i] = x; |
| slice | b = a[l:r] O(k) copy | b := a[l:r] O(1) view | b = a.slice(l, r) O(k) | vector<int> b(a.begin()+l, a.begin()+r); O(k) |
| Python | Go | TypeScript | C++ | |
|---|---|---|---|---|
| append amortized O(1) | a.append(x) | a = append(a, x) | a.push(x) | a.push_back(x); |
| extend k items O(k) | a.extend(xs) | a = append(a, xs...) | a.push(...xs) | a.insert(a.end(), xs.begin(), xs.end()); |
| insert at i O(n) | a.insert(i, x) | a = slices.Insert(a, i, x) | a.splice(i, 0, x) | a.insert(a.begin()+i, x); |
| delete at i O(n) | x = a.pop(i) | a = slices.Delete(a, i, i+1) | a.splice(i, 1) | a.erase(a.begin()+i); |
| pop end O(1) | x = a.pop() | x := a[len(a)-1]; a = a[:len(a)-1] | x = a.pop() | x = a.back(); a.pop_back(); |
| Python | Go | TypeScript | C++ | |
|---|---|---|---|---|
| values O(n) | for x in a: print(x) | for _, x := range a {} | for (const x of a) {} | for (int x : a) {} |
| index + value O(n) | for i, x in enumerate(a): print(i, x) | for i, x := range a {} | for (const [i, x] of a.entries()) {} | for (size_t i = 0; i < a.size(); ++i) {} |
| reverse O(n) | for x in reversed(a): print(x) | for i := len(a)-1; i >= 0; i-- {} | for (let i = a.length-1; i >= 0; i--) {} | for (auto it = a.rbegin(); it != a.rend(); ++it) {} |
| Python | Go | TypeScript | C++ | |
|---|---|---|---|---|
| create / index O(1) | s = "abc"; ch = s[i] | s := "abc"; b := s[i] | const s = "abc"; const ch = s[i] | string s = "abc"; char c = s[i]; |
| slice | t = s[l:r] O(k) | t := s[l:r] bytes | t = s.slice(l, r) code units | t = s.substr(l, k); O(k) |
| split O(n) | parts = s.split(",") | parts := strings.Split(s, ",") | parts = s.split(",") | while (getline(ss, part, ',')) {} |
| join O(total) | out = ",".join(parts) | out := strings.Join(parts, ",") | out = parts.join(",") | ostringstream out; out << part; |
| build O(total) | buf = []; buf.append(x); out = "".join(buf) | var b strings.Builder; b.WriteString(x) | buf.push(x); out = buf.join("") | out.reserve(n); out += x; |
list is mutable; str is immutable. s[i] = "x" is illegal; build a new string.s += piece inside a loop can become O(n^2). Collect pieces in a list, then use "".join(parts).append may reuse the backing array or allocate a new one; keep the returned slice, and remember a[l:r] aliases.string values are immutable bytes. Use range for runes; s[i] is one byte, not one character.delete a[i] leaves a hole and does not shrink length; sparse arrays skip holes in some methods.s.length and s[i] can split emoji or non-BMP characters.vector growth can reallocate; pointers, references, and iterators into it may become invalid.string_view does not own text. Never return a view into a local string.Docs: docs.python.org/stdtypes; pkg.go.dev/builtin#append; pkg.go.dev/slices; pkg.go.dev/strings; developer.mozilla.org/Array; developer.mozilla.org/String; en.cppreference.com/vector; en.cppreference.com/string; en.cppreference.com/string_view