Как удалить элемент из массива в D - PullRequest
12 голосов
/ 16 мая 2011

Конкатенация элемента x в массив items проста в D, как если бы это был список массивов:

arr ~= x;

но как мне удалить anэлемент с индексом 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

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

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

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

Ответы [ 5 ]

20 голосов
/ 16 мая 2011

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

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

Андрей

12 голосов
/ 16 мая 2011

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

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

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

3 голосов
/ 16 мая 2011

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

1 голос
/ 26 мая 2014

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

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

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

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

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

0 голосов
/ 16 мая 2011

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

...