or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

element-management.mdindex.mdmutable-operations.mdset-operations.md

mutable-operations.mddocs/

0

# Mutable Operations

1

2

Mutating operations available exclusively on Multiset instances for modifying multiset contents. These operations modify the multiset in-place and are not available on FrozenMultiset instances.

3

4

## Capabilities

5

6

### Element Addition and Removal

7

8

Add and remove individual elements with precise multiplicity control.

9

10

```python { .api }

11

def add(self, element, multiplicity: int = 1) -> None:

12

"""

13

Add an element to the multiset with specified multiplicity.

14

15

Parameters:

16

- element: Element to add (must be hashable)

17

- multiplicity: Number of times to add element (default: 1)

18

19

Raises:

20

ValueError: If multiplicity is negative

21

"""

22

23

def remove(self, element, multiplicity: Optional[int] = None) -> int:

24

"""

25

Remove element from multiset and return removed multiplicity.

26

27

Parameters:

28

- element: Element to remove

29

- multiplicity: Number to remove (default: remove all)

30

31

Returns:

32

Number of elements actually removed

33

34

Raises:

35

KeyError: If element not present in multiset

36

"""

37

38

def discard(self, element, multiplicity: Optional[int] = None) -> int:

39

"""

40

Remove element from multiset without raising error if not present.

41

42

Parameters:

43

- element: Element to remove

44

- multiplicity: Number to remove (default: remove all)

45

46

Returns:

47

Number of elements actually removed (0 if not present)

48

"""

49

50

def pop(self, element, default: int) -> int:

51

"""

52

Remove element and return its multiplicity.

53

54

Parameters:

55

- element: Element to remove

56

- default: Value to return if element not present

57

58

Returns:

59

Multiplicity of removed element or default value

60

61

Raises:

62

KeyError: If element not present and no default provided

63

"""

64

65

def clear(self) -> None:

66

"""Remove all elements from the multiset."""

67

```

68

69

**Usage Examples:**

70

71

```python

72

from multiset import Multiset

73

74

ms = Multiset('aab') # {'a': 2, 'b': 1}

75

76

# Add elements

77

ms.add('c') # Add 'c' once: {'a': 2, 'b': 1, 'c': 1}

78

ms.add('a', 3) # Add 'a' three times: {'a': 5, 'b': 1, 'c': 1}

79

80

# Remove elements

81

removed = ms.remove('a', 2) # Remove 2 'a's, returns 2: {'a': 3, 'b': 1, 'c': 1}

82

removed = ms.discard('z', 1) # Try to remove 'z', returns 0: unchanged

83

removed = ms.remove('b') # Remove all 'b's, returns 1: {'a': 3, 'c': 1}

84

85

# Pop elements

86

count = ms.pop('c') # Remove and return count of 'c': 1

87

count = ms.pop('z', 0) # Pop 'z' with provided default: returns 0

88

89

# Clear all

90

ms.clear() # Empty multiset: {}

91

```

92

93

### Direct Assignment Operations

94

95

Set element multiplicities directly using dictionary-like assignment.

96

97

```python { .api }

98

def __setitem__(self, element, multiplicity: int) -> None:

99

"""

100

Set the multiplicity of an element directly.

101

102

Parameters:

103

- element: Element to set multiplicity for

104

- multiplicity: New multiplicity (removes element if 0)

105

106

Raises:

107

ValueError: If multiplicity is negative

108

"""

109

110

def __delitem__(self, element) -> None:

111

"""

112

Remove element completely from multiset.

113

114

Parameters:

115

- element: Element to remove

116

117

Raises:

118

KeyError: If element not present

119

"""

120

121

def setdefault(self, element, default: int = 1) -> int:

122

"""

123

Get multiplicity of element, setting to default if not present.

124

125

Parameters:

126

- element: Element to get or set

127

- default: Multiplicity to set if element not present

128

129

Returns:

130

Current or newly set multiplicity

131

"""

132

```

133

134

**Usage Examples:**

135

136

```python

137

ms = Multiset('ab') # {'a': 1, 'b': 1}

138

139

# Direct assignment

140

ms['c'] = 3 # Set 'c' to multiplicity 3: {'a': 1, 'b': 1, 'c': 3}

141

ms['a'] = 5 # Change 'a' to multiplicity 5: {'a': 5, 'b': 1, 'c': 3}

142

ms['b'] = 0 # Remove 'b' by setting to 0: {'a': 5, 'c': 3}

143

144

# Delete elements

145

del ms['c'] # Remove 'c' completely: {'a': 5}

146

147

# Set with default

148

count = ms.setdefault('x', 2) # Set 'x' to 2, returns 2: {'a': 5, 'x': 2}

149

count = ms.setdefault('a', 10) # 'a' exists, returns 5: unchanged

150

```

151

152

### Bulk Update Operations

153

154

Update multiset contents from other collections with various combination strategies.

155

156

```python { .api }

157

def update(self, *others, **kwargs) -> None:

158

"""

159

Add elements from others to this multiset (sum multiplicities).

160

161

Parameters:

162

- *others: Iterables or mappings to add elements from

163

- **kwargs: Additional element-multiplicity pairs

164

"""

165

166

def union_update(self, *others) -> None:

167

"""

168

Update multiset with union of this multiset and others.

169

Takes maximum multiplicity for each element.

170

171

Parameters:

172

- *others: Iterables or mappings to union with

173

"""

174

175

def intersection_update(self, *others) -> None:

176

"""

177

Update multiset with intersection of this multiset and others.

178

Keeps only common elements with minimum multiplicities.

179

180

Parameters:

181

- *others: Iterables or mappings to intersect with

182

"""

183

184

def difference_update(self, *others) -> None:

185

"""

186

Remove elements of others from this multiset.

187

188

Parameters:

189

- *others: Iterables or mappings to subtract

190

"""

191

192

def symmetric_difference_update(self, other) -> None:

193

"""

194

Update multiset with symmetric difference.

195

196

Parameters:

197

- other: Iterable or mapping to compute symmetric difference with

198

"""

199

200

def times_update(self, factor: int) -> None:

201

"""

202

Scale all multiplicities by factor in-place.

203

204

Parameters:

205

- factor: Scaling factor (must be non-negative)

206

207

Raises:

208

ValueError: If factor is negative

209

"""

210

```

211

212

**Usage Examples:**

213

214

```python

215

ms = Multiset('aab') # {'a': 2, 'b': 1}

216

217

# Update (combine/add multiplicities)

218

ms.update('abc') # Add from string: {'a': 3, 'b': 2, 'c': 1}

219

ms.update({'x': 2, 'y': 1}) # Add from mapping: {'a': 3, 'b': 2, 'c': 1, 'x': 2, 'y': 1}

220

221

# Union update (maximum multiplicities)

222

ms2 = Multiset('aaax') # {'a': 3, 'x': 1}

223

ms.union_update(ms2) # Take max: {'a': 3, 'b': 2, 'c': 1, 'x': 2, 'y': 1}

224

225

# Intersection update (minimum multiplicities, common elements only)

226

ms.intersection_update('axyz') # Keep common: {'a': 1, 'x': 1, 'y': 1}

227

228

# Difference update (subtract)

229

ms.difference_update('ay') # Remove: {'x': 1}

230

231

# Times update (scale)

232

ms.times_update(3) # Scale by 3: {'x': 3}

233

```

234

235

### In-Place Operators

236

237

Convenient operators for in-place multiset operations.

238

239

```python { .api }

240

def __ior__(self, other) -> Multiset:

241

"""In-place union using |= operator."""

242

243

def __iand__(self, other) -> Multiset:

244

"""In-place intersection using &= operator."""

245

246

def __isub__(self, other) -> Multiset:

247

"""In-place difference using -= operator."""

248

249

def __ixor__(self, other) -> Multiset:

250

"""In-place symmetric difference using ^= operator."""

251

252

def __imul__(self, factor: int) -> Multiset:

253

"""In-place scaling using *= operator."""

254

```

255

256

**Usage Examples:**

257

258

```python

259

ms1 = Multiset('aab') # {'a': 2, 'b': 1}

260

ms2 = Multiset('abc') # {'a': 1, 'b': 1, 'c': 1}

261

262

# In-place operations using operators

263

ms1 |= ms2 # Union: {'a': 2, 'b': 1, 'c': 1}

264

ms1 &= 'ab' # Intersection: {'a': 1, 'b': 1}

265

ms1 -= 'a' # Difference: {'b': 1}

266

ms1 *= 4 # Scale: {'b': 4}

267

268

# Note: += uses update() method for combination

269

ms1 += 'bb' # Combine: {'b': 6}

270

```

271

272

### Mutable-Specific Features

273

274

Features that distinguish mutable multisets from their immutable counterparts.

275

276

**Mutability Characteristics:**

277

278

```python

279

# Mutable multisets can be modified after creation

280

ms = Multiset('abc')

281

ms.add('d') # Allowed on Multiset

282

ms['e'] = 2 # Allowed on Multiset

283

284

# Immutable multisets cannot be modified

285

frozen_ms = FrozenMultiset('abc')

286

# frozen_ms.add('d') # AttributeError: not available

287

# frozen_ms['e'] = 2 # TypeError: not supported

288

289

# Mutable multisets are not hashable

290

# hash(ms) # TypeError: unhashable type

291

hash(frozen_ms) # Works: returns hash value

292

293

# Use in sets/dicts

294

my_set = {frozen_ms} # Allowed

295

# my_set = {ms} # TypeError: unhashable type

296

```

297

298

**Thread Safety Considerations:**

299

300

```python

301

# Mutable multisets are not thread-safe

302

# Concurrent modifications require external synchronization

303

import threading

304

305

ms = Multiset()

306

lock = threading.Lock()

307

308

def safe_add(element):

309

with lock:

310

ms.add(element)

311

312

# Use FrozenMultiset for read-only sharing between threads

313

shared_ms = FrozenMultiset('abc') # Safe to share

314

```

315

316

**Performance Notes:**

317

318

```python

319

# Bulk operations are more efficient than individual operations

320

ms = Multiset()

321

322

# Efficient: single bulk operation

323

ms.update('abcdefg' * 1000)

324

325

# Less efficient: many individual operations

326

# for char in 'abcdefg' * 1000:

327

# ms.add(char)

328

329

# In-place operations modify existing multiset

330

ms = Multiset('aaa')

331

original_id = id(ms)

332

ms += 'bbb' # Modifies existing multiset

333

assert id(ms) == original_id # Same object

334

335

# Regular operations create new multisets

336

result = ms + 'ccc' # Creates new multiset

337

assert id(result) != id(ms) # Different objects

338

```