Skip to content

Commit d4b83eb

Browse files
committed
delete method for namedlist/names
1 parent 0295b06 commit d4b83eb

File tree

4 files changed

+167
-0
lines changed

4 files changed

+167
-0
lines changed

src/biocutils/named_list.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,47 @@ def __iadd__(self, other: list):
435435
self.extend(other)
436436
return self
437437

438+
def safe_delete(self, index: Union[int, str, slice], in_place: bool = False) -> NamedList:
439+
"""
440+
Args:
441+
index:
442+
An integer index or slice containing position(s) to delete.
443+
Alternatively, the name of the value to delete (the first
444+
occurrence of the name is used).
445+
446+
in_place:
447+
Whether to modify the current object in place.
448+
449+
Returns:
450+
A ``NamedList`` where the item at ``index`` is removed. This is a
451+
new object if ``in_place = False``, otherwise it is a reference to
452+
the current object.
453+
"""
454+
if in_place:
455+
output = self
456+
else:
457+
output = self._shallow_copy()
458+
output._data = output._data[:] # Shallow copy of the list
459+
if output._names is not None:
460+
output._names = output._names.copy()
461+
462+
if isinstance(index, str):
463+
index = _name_to_position(self._names, index)
464+
465+
del output._data[index]
466+
if output._names is not None:
467+
output._names.delete(index)
468+
469+
return output
470+
471+
def delete(self, index: Union[int, str, slice]):
472+
"""Alias for :py:meth:`~safe_delete` with ``in_place = True``."""
473+
self.safe_delete(index, in_place=True)
474+
475+
def __delitem__(self, index: Union[int, str, slice]):
476+
"""Alias for :py:meth:`~delete`."""
477+
self.delete(index)
478+
438479
################################
439480
#####>>>> Copy methods <<<<#####
440481
################################

src/biocutils/names.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,35 @@ def __iadd__(self, other: list):
328328
self.extend(other)
329329
return self
330330

331+
def safe_delete(self, index: Union[int, slice], in_place: bool = False) -> Names:
332+
"""
333+
Args:
334+
index:
335+
Position(s) of the name(s) to delete.
336+
337+
in_place:
338+
Whether to perform this deletion in-place.
339+
340+
Returns:
341+
A ``Names`` object with the deleted name(s). This is a new object
342+
if ``in_place = False``, otherwise it is a reference to the current
343+
object.
344+
"""
345+
output = self._define_output(in_place)
346+
if in_place:
347+
output._wipe_reverse_index()
348+
349+
del output._names[index]
350+
return output
351+
352+
def delete(self, index: Union[int, slice]):
353+
"""Alias for :py:attr:`~safe_delete` with ``in_place = True``."""
354+
self.safe_delete(index, in_place=True)
355+
356+
def __delitem__(self, index: Union[int, slice]):
357+
"""Alias for :py:attr:`~delete`."""
358+
self.delete(index)
359+
331360
################################
332361
#####>>>> Copy methods <<<<#####
333362
################################

tests/test_NamedList.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,58 @@ def test_NamedList_generics():
257257
y = biocutils.assign_sequence(x, [1, 3], NamedList([ 20, 40 ], names=["b", "d" ]))
258258
assert y.as_list() == [ 1, 20, 3, 40 ]
259259
assert y.get_names().as_list() == [ "A", "B", "C", "D" ] # doesn't set the names, as per policy.
260+
261+
def test_NamedList_safe_delete():
262+
x = NamedList([1, 2, 3, 4], names=["A", "B", "C", "D"])
263+
264+
y = x.safe_delete(1)
265+
assert y.as_list() == [1, 3, 4]
266+
assert y.get_names().as_list() == ["A", "C", "D"]
267+
assert x.as_list() == [1, 2, 3, 4]
268+
269+
y = x.safe_delete("C")
270+
assert y.as_list() == [1, 2, 4]
271+
assert y.get_names().as_list() == ["A", "B", "D"]
272+
273+
y = x.safe_delete(slice(1, 3))
274+
assert y.as_list() == [1, 4]
275+
assert y.get_names().as_list() == ["A", "D"]
276+
277+
y = x.safe_delete(-1)
278+
assert y.as_list() == [1, 2, 3]
279+
assert y.get_names().as_list() == ["A", "B", "C"]
280+
281+
282+
def test_NamedList_delete():
283+
x = NamedList([1, 2, 3, 4], names=["A", "B", "C", "D"])
284+
285+
x.delete(0)
286+
assert x.as_list() == [2, 3, 4]
287+
assert x.get_names().as_list() == ["B", "C", "D"]
288+
289+
x.delete("D")
290+
assert x.as_list() == [2, 3]
291+
assert x.get_names().as_list() == ["B", "C"]
292+
293+
294+
def test_NamedList_delitem():
295+
x = NamedList([1, 2, 3, 4], names=["A", "B", "C", "D"])
296+
297+
del x[1]
298+
assert x.as_list() == [1, 3, 4]
299+
assert x.get_names().as_list() == ["A", "C", "D"]
300+
301+
del x["A"]
302+
assert x.as_list() == [3, 4]
303+
assert x.get_names().as_list() == ["C", "D"]
304+
305+
x = NamedList([1, 2, 3, 4], names=["A", "B", "C", "D"])
306+
del x[0:2]
307+
assert x.as_list() == [3, 4]
308+
assert x.get_names().as_list() == ["C", "D"]
309+
310+
with pytest.raises(KeyError):
311+
del x["Missing"]
312+
313+
with pytest.raises(IndexError):
314+
del x[10]

tests/test_Names.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,45 @@ def test_Names_generics():
195195
ass = biocutils.assign_sequence(x, range(1, 3), y)
196196
assert isinstance(ass, Names)
197197
assert ass.as_list() == ["1", "b", "c", "4"]
198+
199+
def test_Names_safe_delete():
200+
x = Names(["A", "B", "C", "D"])
201+
202+
y = x.safe_delete(1)
203+
assert y.as_list() == ["A", "C", "D"]
204+
assert y.map("B") == -1
205+
assert y.map("C") == 1
206+
assert x.as_list() == ["A", "B", "C", "D"]
207+
208+
y = x.safe_delete(slice(0, 2))
209+
assert y.as_list() == ["C", "D"]
210+
assert y.map("A") == -1
211+
assert y.map("C") == 0
212+
213+
214+
def test_Names_delete():
215+
x = Names(["A", "B", "C", "D"])
216+
217+
x.delete(2)
218+
assert x.as_list() == ["A", "B", "D"]
219+
assert x.map("C") == -1
220+
assert x.map("D") == 2
221+
222+
x.delete(0)
223+
assert x.as_list() == ["B", "D"]
224+
assert x.map("A") == -1
225+
assert x.map("B") == 0
226+
227+
228+
def test_Names_delitem():
229+
x = Names(["1", "2", "3", "4"])
230+
231+
del x[1]
232+
assert x.as_list() == ["1", "3", "4"]
233+
assert x.map("2") == -1
234+
assert x.map("3") == 1
235+
236+
del x[0:2]
237+
assert x.as_list() == ["4"]
238+
assert x.map("1") == -1
239+
assert x.map("4") == 0

0 commit comments

Comments
 (0)