mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Implement array delitem by slice
This commit is contained in:
1 parent
2cd634f956
commit
fa6b8208ec
3 files changed
+84
-4
No files matched your search
@@ -890,7 +890,7 @@ class BaseTest:
|
||||
self.assertRaises(TypeError, a.__setitem__, slice(0, 1), b)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# @unittest.expectedFailure
|
||||
def test_extended_set_del_slice(self):
|
||||
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
|
||||
for start in indices:
|
||||
@@ -1214,7 +1214,7 @@ class NumberTest(BaseTest):
|
||||
self.assertEqual(a[-1000:-2000:-2], array.array(self.typecode, []))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# @unittest.expectedFailure
|
||||
def test_delslice(self):
|
||||
a = array.array(self.typecode, range(5))
|
||||
del a[::2]
|
||||
|
||||
@@ -34,3 +34,11 @@ a[0:0:9999999999] = c
|
||||
assert a == array(T, [100, 1, 2, 3, 4, 5, 6, 7, 8, 100])
|
||||
a[0:0:-9999999999] = c
|
||||
assert a == array(T, [100, 1, 2, 3, 4, 5, 6, 7, 8, 100])
|
||||
del a[::9999999999]
|
||||
assert a == array(T, [1, 2, 3, 4, 5, 6, 7, 8, 100])
|
||||
del a[::-9999999999]
|
||||
assert a == array(T, [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
del a[0:0:9999999999]
|
||||
assert a == array(T, [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
del a[0:0:-9999999999]
|
||||
assert a == array(T, [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
+74
-2
@@ -344,7 +344,79 @@ macro_rules! def_array_enum {
|
||||
}
|
||||
|
||||
fn delitem_by_slice(&mut self, slice: PySliceRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_not_implemented_error("FIX NOW".to_owned()))
|
||||
let start = slice.start_index(vm)?;
|
||||
let stop = slice.stop_index(vm)?;
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
|
||||
if step.is_zero() {
|
||||
return Err(vm.new_value_error("slice step cannot be zero".to_owned()));
|
||||
}
|
||||
|
||||
match self {
|
||||
$(ArrayContentType::$n(elements) => {
|
||||
if step == BigInt::one() {
|
||||
let range = get_slice_range(&start, &stop, elements.len());
|
||||
if range.start < range.end {
|
||||
elements.drain(range);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (start, stop, step, is_negative_step) = if step.is_negative() {
|
||||
(
|
||||
stop.map(|x| if x == -BigInt::one() {
|
||||
elements.len() + BigInt::one()
|
||||
} else {
|
||||
x + 1
|
||||
}),
|
||||
start.map(|x| if x == -BigInt::one() {
|
||||
BigInt::from(elements.len())
|
||||
} else {
|
||||
x + 1
|
||||
}),
|
||||
-step,
|
||||
true
|
||||
)
|
||||
} else {
|
||||
(start, stop, step, false)
|
||||
};
|
||||
|
||||
let range = get_slice_range(&start, &stop, elements.len());
|
||||
if range.start >= range.end {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// step is not negative here
|
||||
if let Some(step) = step.to_usize() {
|
||||
let mut indexes = if is_negative_step {
|
||||
itertools::Either::Left(range.clone().rev().step_by(step).rev()).peekable()
|
||||
} else {
|
||||
itertools::Either::Right(range.clone().step_by(step)).peekable()
|
||||
};
|
||||
|
||||
let mut deleted = 0;
|
||||
|
||||
// passing whole range, swap or overlap
|
||||
for i in range.clone() {
|
||||
if indexes.peek() == Some(&i) {
|
||||
indexes.next();
|
||||
deleted += 1;
|
||||
} else {
|
||||
elements.swap(i - deleted, i);
|
||||
}
|
||||
}
|
||||
// then drain (the values to delete should now be contiguous at the end of the range)
|
||||
elements.drain((range.end - deleted)..range.end);
|
||||
} else {
|
||||
// edge case, step is too big for usize
|
||||
// same behaviour as CPython
|
||||
elements.remove(
|
||||
if is_negative_step { range.end -1 } else { range.start }
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
fn repr(&self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
@@ -596,7 +668,7 @@ impl PyArray {
|
||||
fn delitem(&self, needle: Either<isize, PySliceRef>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
match needle {
|
||||
Either::A(i) => self.borrow_value_mut().delitem_by_idx(i, vm),
|
||||
Either::B(slice) => self.borrow_value_mut().delitem_by_slice(slice, vm)
|
||||
Either::B(slice) => self.borrow_value_mut().delitem_by_slice(slice, vm),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user