我需要一个动态长度的数据结构,能够更改元素值。 元素的顺序并不重要。
如果我使用数组,我可以修改我的元素,但是我的长度有问题。解决方案是创建一个正确大小的新数组,并每次将所有元素复制到新数组中。不是一个好主意,因为元素的数量经常变化。
最好使用通用列表,但修改过程非常复杂:首先我需要删除我想要更改的元素 - 通用列表似乎没有简单的“删除” /“删除”方法,所以我尝试了“过滤”一个 - 然后将修改后的元素添加到头部。它有效,但对于这么简单的东西来说有点太复杂了。
是否有数据结构允许我动态更改长度并修改元素,例如可修改列表或动态大小的数组?
答案 0 :(得分:7)
使用ResizeArray。它是CLI类型List(T)的缩写,它提供了您需要的功能,例如Remove。
来自MSDN Library:
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)要排序。
可以使用整数索引访问此集合中的元素。 此集合中的索引从零开始。
List(T)接受空引用(在Visual Basic中为Nothing)作为有效引用 引用类型的值,并允许重复的元素。
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]
答案 1 :(得分:5)
我建议使用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
进行优化。