0
# Setlists and Ordered Sets
1
2
Setlists are ordered collections of unique elements that combine list-like indexing with set-like uniqueness constraints. They maintain insertion order while enforcing element uniqueness, providing efficient index-based access and set operations.
3
4
## Capabilities
5
6
### Setlist Construction
7
8
Create ordered sets from iterables with automatic duplicate removal.
9
10
```python { .api }
11
class SetList:
12
def __init__(self, iterable=None, raise_on_duplicate=False):
13
"""Create a setlist from an iterable.
14
15
Args:
16
iterable: Values to initialize the setlist with
17
raise_on_duplicate: If True, raise ValueError on duplicate values
18
"""
19
20
def setlist(iterable=None, raise_on_duplicate=False):
21
"""Create a mutable setlist from an iterable."""
22
23
def frozensetlist(iterable=None, raise_on_duplicate=False):
24
"""Create an immutable, hashable setlist from an iterable."""
25
```
26
27
Usage examples:
28
```python
29
from collections_extended import setlist, frozensetlist
30
31
# Create from string - duplicates removed, order preserved
32
sl = setlist('abracadabra')
33
print(sl) # setlist(('a', 'b', 'r', 'c', 'd'))
34
35
# Raise error on duplicates
36
try:
37
sl = setlist('hello', raise_on_duplicate=True)
38
except ValueError:
39
print("Duplicate 'l' found")
40
41
# Create immutable setlist
42
fsl = frozensetlist([1, 2, 3, 2, 1])
43
print(len(fsl)) # 3
44
```
45
46
### Sequence Operations
47
48
Access and query elements using list-like indexing and sequence operations.
49
50
```python { .api }
51
def __getitem__(self, index):
52
"""Get element at index or slice.
53
54
Args:
55
index: int or slice object
56
57
Returns:
58
Element at index or new setlist for slices
59
"""
60
61
def index(self, value, start=0, end=None):
62
"""Return index of value between start and end.
63
64
Args:
65
value: Element to find
66
start: Start index for search
67
end: End index for search
68
69
Returns:
70
int: Index of the element
71
72
Raises:
73
ValueError: If value not found or outside start-end range
74
"""
75
76
def count(self, value):
77
"""Return count of value (always 0 or 1 for setlists).
78
79
Args:
80
value: Element to count
81
82
Returns:
83
int: 1 if value in setlist, 0 otherwise
84
"""
85
86
def sub_index(self, sub, start=0, end=None):
87
"""Return index of a subsequence.
88
89
Args:
90
sub: Sequence to search for
91
start: Start index for search
92
end: End index for search
93
94
Returns:
95
int: Index of first element of subsequence
96
97
Raises:
98
ValueError: If subsequence not found
99
"""
100
```
101
102
Usage examples:
103
```python
104
sl = setlist('abcde')
105
print(sl[2]) # 'c'
106
print(sl[1:4]) # setlist(('b', 'c', 'd'))
107
print(sl.index('d')) # 3
108
print(sl.count('c')) # 1
109
print(sl.sub_index(['b', 'c'])) # 1
110
```
111
112
### Mutable Setlist Operations
113
114
Modify setlist contents while maintaining uniqueness constraints.
115
116
```python { .api }
117
def append(self, value):
118
"""Append value to the end.
119
120
Args:
121
value: Value to append
122
123
Raises:
124
ValueError: If value already in setlist
125
"""
126
127
def insert(self, index, value):
128
"""Insert value at index.
129
130
Args:
131
index: Position to insert at
132
value: Value to insert
133
134
Raises:
135
ValueError: If value already in setlist
136
"""
137
138
def extend(self, values):
139
"""Append all values to the end.
140
141
Args:
142
values: Iterable of values to append
143
144
Raises:
145
ValueError: If any value already present or duplicates in values
146
"""
147
148
def remove(self, value):
149
"""Remove value from setlist.
150
151
Args:
152
value: Element to remove
153
154
Raises:
155
ValueError: If value not present
156
"""
157
158
def pop(self, index=-1):
159
"""Remove and return item at index.
160
161
Args:
162
index: Index to pop (default: last item)
163
164
Returns:
165
Any: The removed element
166
"""
167
168
def clear(self):
169
"""Remove all elements from setlist."""
170
171
def reverse(self):
172
"""Reverse the setlist in-place."""
173
174
def sort(self, *args, **kwargs):
175
"""Sort the setlist in-place."""
176
177
def swap(self, i, j):
178
"""Swap elements at indices i and j."""
179
```
180
181
Usage examples:
182
```python
183
sl = setlist(['a', 'b', 'c'])
184
sl.append('d') # setlist(['a', 'b', 'c', 'd'])
185
sl.insert(1, 'x') # setlist(['a', 'x', 'b', 'c', 'd'])
186
sl.extend(['e', 'f']) # setlist(['a', 'x', 'b', 'c', 'd', 'e', 'f'])
187
188
item = sl.pop() # 'f', setlist now ['a', 'x', 'b', 'c', 'd', 'e']
189
sl.remove('x') # setlist(['a', 'b', 'c', 'd', 'e'])
190
sl.reverse() # setlist(['e', 'd', 'c', 'b', 'a'])
191
```
192
193
### Set Operations
194
195
Mathematical set operations that preserve order based on the left operand.
196
197
```python { .api }
198
def union(self, other):
199
"""Return union of setlists (all elements from both)."""
200
201
def intersection(self, other):
202
"""Return intersection of setlists (common elements)."""
203
204
def difference(self, other):
205
"""Return difference of setlists (elements in self but not other)."""
206
207
def symmetric_difference(self, other):
208
"""Return symmetric difference (elements in either but not both)."""
209
210
def __add__(self, other):
211
"""Concatenate setlists (other elements appended, duplicates raise error)."""
212
213
def __sub__(self, other):
214
"""Return difference of setlists."""
215
216
def __and__(self, other):
217
"""Return intersection of setlists."""
218
219
def __or__(self, other):
220
"""Return union of setlists."""
221
222
def __xor__(self, other):
223
"""Return symmetric difference of setlists."""
224
225
def issubset(self, other):
226
"""Check if all elements are in other."""
227
228
def issuperset(self, other):
229
"""Check if all elements of other are in self."""
230
```
231
232
Usage examples:
233
```python
234
sl1 = setlist('abc')
235
sl2 = setlist('bcd')
236
237
print(sl1 | sl2) # setlist(['a', 'b', 'c', 'd']) (union)
238
print(sl1 & sl2) # setlist(['b', 'c']) (intersection)
239
print(sl1 - sl2) # setlist(['a']) (difference)
240
print(sl1 ^ sl2) # setlist(['a', 'd']) (symmetric difference)
241
242
print(setlist('ab').issubset(sl1)) # True
243
```
244
245
### Set-like Mutable Operations
246
247
Mutable set operations that modify the setlist in-place.
248
249
```python { .api }
250
def add(self, item):
251
"""Add item if not already present (like set.add)."""
252
253
def update(self, values):
254
"""Add all values, ignoring duplicates (like set.update)."""
255
256
def discard(self, value):
257
"""Remove value if present, silent if missing (like set.discard)."""
258
259
def discard_all(self, elems_to_delete):
260
"""Remove all elements in elems_to_delete, ignoring missing."""
261
262
def remove_all(self, elems_to_delete):
263
"""Remove all elements in elems_to_delete.
264
265
Raises:
266
ValueError: If any element not present or duplicates in elems_to_delete
267
"""
268
269
def difference_update(self, other):
270
"""Remove all elements in other from self."""
271
272
def intersection_update(self, other):
273
"""Keep only elements also in other."""
274
275
def symmetric_difference_update(self, other):
276
"""Update to symmetric difference with other."""
277
```
278
279
Usage examples:
280
```python
281
sl = setlist('abc')
282
sl.add('d') # setlist(['a', 'b', 'c', 'd'])
283
sl.add('b') # No change - 'b' already present
284
sl.update('efg') # setlist(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
285
sl.discard('x') # No error - 'x' not present
286
sl.discard_all('aei') # Removes 'a' and 'e', ignores 'i'
287
```
288
289
### Sequence-like Mutable Operations
290
291
Additional list-like operations for fine-grained control.
292
293
```python { .api }
294
def __setitem__(self, index, value):
295
"""Set element at index to value.
296
297
Args:
298
index: int or slice
299
value: New value or sequence of values
300
301
Raises:
302
ValueError: If value already exists elsewhere in setlist
303
"""
304
305
def __delitem__(self, index):
306
"""Delete element at index or slice."""
307
308
def shuffle(self, random=None):
309
"""Shuffle elements in-place.
310
311
Args:
312
random: Random function (default: random.random)
313
"""
314
```
315
316
Usage examples:
317
```python
318
sl = setlist(['a', 'b', 'c', 'd'])
319
sl[1] = 'x' # setlist(['a', 'x', 'c', 'd'])
320
del sl[0] # setlist(['x', 'c', 'd'])
321
sl.shuffle() # Random order, e.g., setlist(['d', 'x', 'c'])
322
```
323
324
### Immutable Setlists
325
326
Create hashable, immutable versions for use as dictionary keys or set elements.
327
328
```python { .api }
329
class frozensetlist(SetList, Hashable):
330
def __hash__(self):
331
"""Return hash value for the frozensetlist."""
332
```
333
334
Usage examples:
335
```python
336
from collections_extended import frozensetlist
337
338
# Immutable setlists can be dict keys
339
fsl1 = frozensetlist('abc')
340
fsl2 = frozensetlist('def')
341
mapping = {fsl1: 'first', fsl2: 'second'}
342
343
# Or in sets
344
setlist_set = {frozensetlist('hello'), frozensetlist('world')}
345
```
346
347
### Copy and Comparison
348
349
Create copies and compare setlists efficiently.
350
351
```python { .api }
352
def copy(self):
353
"""Return a shallow copy of the setlist."""
354
355
def __eq__(self, other):
356
"""Check equality with another setlist (order matters)."""
357
358
def __ne__(self, other):
359
"""Check inequality with another setlist."""
360
```