Список, массив или что еще?

Мне нужна структура данных динамической длины с возможностью изменения значений элементов. Порядок элементов не важен.

  • Если я использую массив, я могу изменить свои элементы, но у меня проблемы с длиной. Решением является создание нового массива правильного размера и копирование всех элементов в новый каждый раз. Не очень хорошая идея, потому что количество элементов часто меняется.

  • Лучше использовать общий список, но процесс изменения действительно сложный: прежде всего мне нужно удалить элемент, который я хочу изменить, - общий список, похоже, не имеет простого "Удалить", / "Удалить", поэтому я попробовал "Фильтровать", а затем добавил измененный элемент в голову. Это работает, но это слишком сложно для чего-то очень легкого.

Есть ли структура данных, которая позволяет мне динамически изменять длину и изменять такие элементы, как модифицируемый список или массив с динамическим размером?

Ответы

Ответ 1

Используйте ResizeArray. Это аббревиатура для типа CLI List (T), который предлагает требуемые функции, например Удалить, например.

Из библиотеки MSDN:

Класс List (T) является общим эквивалентом класса ArrayList. Это реализует общий интерфейс IList (T), используя массив, размер которого равен динамически увеличиваются по мере необходимости.

Такие методы, как Contains, IndexOf, LastIndexOf и Удалить, используют равенство для элементов списка. Средство сравнения по умолчанию для типа T определяется следующим образом. Если тип T реализует IEquatable (T), тогда сравнительный коэффициент равен Метод Equals (T) этого интерфейса; в противном случае равенство по умолчанию Comparer - Object.Equals(Object).

В методах, таких как BinarySearch и Sort, используется сопоставитель заказов для элементов списка. Сравнение по умолчанию для типа T определяется как следующим образом. Если тип T реализует общий интерфейс IComparable (T) то по умолчанию используется метод CompareTo (T) интерфейс; в противном случае, если тип T реализует неструктурный IComparable интерфейс, то по умолчанию используется метод CompareTo (Object) этого интерфейса. Если тип T не реализует ни интерфейс, не является компаратором по умолчанию, а делегат сравнения или сравнения должен быть явно указано.

Список (T) не может быть отсортирован. Вы должны отсортировать список (T) перед выполнением операций (например, BinarySearch), которые требуют Список (T) для сортировки.

Элементы этой коллекции могут быть доступны с использованием целочисленного индекса. Индексы в этой коллекции основаны на нуле.

Список (T) принимает нулевую ссылку (Nothing в Visual Basic) как действительный значение для ссылочных типов и позволяет дублировать элементы.

Пример в F#:

open System

// an integer list
let intList =
    let temp = new ResizeArray<int>() in
    temp.AddRange([| 1; 2; 3 |]);
    temp

// print each int using the ForEach member method
intList.ForEach( fun i -> Console.WriteLine(i) )

// unpack items from the resize array
let itemOne = intList.Item(0)
let itemTwo = intList.[1]

Ответ 2

Я бы рекомендовал использовать ResizeArray. Это в основном System.Collections.Generic.List < 'T > , которое идеально подходит для использования, если количество элементов изменяется часто.

// Add items to a ResizeArray based on a condition
let filterRange predicate (i, j) =
    let results = ResizeArray(j-i+1) // reserve enough memory
    for k = i to j do
        if predicate k then results.Add(k)
    results

Что касается вашей второй проблемы, вы все равно можете использовать синтаксис arr.[idx] <- e как с Array.

Чтобы избежать сложной манипуляции с ResizeArray, вы можете использовать функции высокого порядка в ResizeArray module из F # PowerPack. Эти функции создают новый ResizeArray, поэтому производительность не идеальна.

// Use high-order functions to update items
let changeOneToThree (a: ResizeArray<_>) =
   ResizeArray.map (fun x -> if x = 1 then 3 else x) a

Однако вы всегда можете начать оттуда и оптимизировать, изменив текущий ResizeArray.