Как удалить элемент из массива в D

Объединение элемента x в массив items легко в D, это как если бы это был список массивов:

arr ~= x;

но как удалить элемент в индексе i из items?

(Предостережение: если я удалю элемент и добавлю новый элемент, массив не должен быть перераспределен. Таким образом, простой срез не будет работать.)


Обновление:

На основании ответа CyberShadow об использовании assumeSafeAppend, я написал этот код:

static void removeAt(T)(ref T[] arr, size_t index)
{
    foreach (i, ref item; arr[index .. $ - 1])
        item = arr[i + 1];
    arr = arr[0 .. $ - 1];
    arr.assumeSafeAppend();
}

Однако проблема возникает, когда у вас есть что-то вроде:

auto superArr = [0, 1, 2, 3, 4]; //Must not be modified
auto arr = superArr[0 .. $ - 1];
writeln(superArr);
arr.removeAt(0);    //Should copy the slice and modify the copy
writeln(superArr);  //but obviously doesn't

Базовый массив среза должен быть не изменен, если элемент удален из среза; вместо этого нужно скопировать фрагмент.

Но у меня нет способа узнать, является ли массив срезом большего массива... так что это не работает.

Любые предложения?

Ответ 1

(Предостережение: если я удалю элемент и добавлю новый элемент, массив не должен быть перераспределен. Таким образом, простой срез не будет работать.)

Функция assumeSafeAppend сообщит, что среда выполнения не перераспределяет массив при добавлении к нему (т.е. это подтверждение от пользователя что нет других фрагментов, которые могут быть сжаты добавлением).

remove из std.algorithm делает удаление на месте. Если вы используете std.container, там также Array.linearRemove.

Ответ 2

Копирование моего ответа на digitalmars.D(спасибо за пересылку):

Как уже упоминалось, std.algorithm.remove может помочь. Возможно, вам захочется взглянуть на три из его возможностей, в частности: (a) удалить несколько смещений за один проход, например. remove (a, 0, 4) удаляет первый и пятый элементы, (b) вы можете удалить поддиапазоны, например. remove (a, кортеж (1, 3)) удаляет второй-четвертый элемент и (c), если вам не нужен порядок, в котором элементы остаются после удаления, вы можете захотеть взглянуть на неустойчивое удаление, что значительно меньше работа.

Андрей

Ответ 3

Хорошо, если порядок не имеет значения, вы можете скопировать последний элемент в место удаления, а затем уменьшить длину массива на единицу.

Ответ 4

Если вы просто хотите удалить первый или последний элементы, используйте срезы:

array = array [1..$]
array = array [0..$-1]

Или общий способ, который работает и для среднего:

array = array [0..unlucky] ~ array [unlucky+1..$]

Если элементы не являются базовыми элементами, такими как structs, floats, ints, тогда массивы являются неявно массивами указателей, и это эффективная операция.

Ответ 5

Нет автоматизированного способа сделать это, вам нужно будет перетасовать элементы массива вдоль, reset.length и затем соединить.