Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 是否有.NET StringBuilder功能版本的开源(非GPL)实现?_F#_Stringbuilder - Fatal编程技术网

F# 是否有.NET StringBuilder功能版本的开源(非GPL)实现?

F# 是否有.NET StringBuilder功能版本的开源(非GPL)实现?,f#,stringbuilder,F#,Stringbuilder,我正在寻找StringBuilder或同等产品的功能性(如非强制性)实现。我见过几个函数数组的实现,但它们不支持本机插入。开源、非-(L?A?)GPL的奖金,F#的奖金,但如果需要,我可以从Haskell/OCaml/SML进行翻译 欢迎对算法提出建议。StringBuilder相对于string的优势在于最小化分配。它预先分配一个缓冲区,以避免为每次插入/追加分配缓冲区。这需要可变性——某些对象必须拥有(并改变)缓冲区 顺便说一句,System.String已经符合(我能理解的)您的描述:它是

我正在寻找StringBuilder或同等产品的功能性(如非强制性)实现。我见过几个函数数组的实现,但它们不支持本机插入。开源、非-(L?A?)GPL的奖金,F#的奖金,但如果需要,我可以从Haskell/OCaml/SML进行翻译


欢迎对算法提出建议。

StringBuilder
相对于
string
的优势在于最小化分配。它预先分配一个缓冲区,以避免为每次插入/追加分配缓冲区。这需要可变性——某些对象必须拥有(并改变)缓冲区

顺便说一句,
System.String
已经符合(我能理解的)您的描述:它是不可变的,支持连接,并且

更新 托马斯的想法引起了我的兴趣。考虑到他的想法,以下是我的想法

type StringBuilder =
  private
  | Empty
  | StringBuilder of int * string * int * StringBuilder
  member this.Length =
    match this with 
    | Empty -> 0
    | StringBuilder(_, _, n, _) -> n
  override this.ToString() =
    let rec rev acc = function
      | Empty -> acc
      | StringBuilder(idx, str, _, bldr) -> rev ((idx, str)::acc) bldr
    let buf = ResizeArray(this.Length)
    for idx, str in rev [] this do buf.InsertRange(idx, str)
    System.String(buf.ToArray())

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module StringBuilder =
  let empty = Empty
  let length (bldr:StringBuilder) = bldr.Length
  let insert index str bldr = 
    if index < 0 || index > (length bldr) then invalidArg "index" "out of range"
    StringBuilder(index, str, str.Length + bldr.Length, bldr)
  let create str = insert 0 str empty
  let append str bldr = insert (length bldr) str bldr
  let remove index count (bldr:StringBuilder) = create <| bldr.ToString().Remove(index, count)

它是持久性的,插入是O(1)。

我不知道有什么实现能完全满足您的要求。然而,我不认为你能得到插入的O(1)复杂度(在任意索引处)和迭代结果的O(n)复杂度

如果您愿意牺牲插入的复杂性,那么可以按照Daniel的建议使用
string
。另一方面,如果您愿意牺牲
toString
的复杂性,那么您可以通过使用字符串和索引列表在任意位置插入O(1)来生成不可变的数据结构:

type InsertList = IL of (int * string) list 

// Insert string 'str' at the specified index 
let insertAt idx str (IL items) = IL (idx, str)::items

// Create insert list from a string
let ofString str = IL [str]

转换为字符串有点棘手。但是,我认为通过使用可变的
LinkedList
并通过从末尾重复插入,在正确的位置插入单个字符,可以获得O(n log n)的复杂性。
LinkedList
的使用将被本地化为
toString
,因此数据结构仍然是纯功能的。

您希望从StringBuilder获得哪些功能和性能?O(1)insert和O(n)toArray?我对性能不是太挑剔,但是是的,理想情况下,O(1)insert和O(n)转换回seq/stream/array。我怀疑O(1)insert在任意位置是否适用于功能数据结构。标准stringbuilder到底出了什么问题?还有,您所说的“功能性”到底是什么意思?Persistent?Immutable是另一个常用于非破坏性数据类型的名称。到字符串的最小转换至少为O(n),因为您必须反转列表以处理
insertAt 0“World”
然后
insertAt 0“Hello”
,然后我认为最好的方法是使用稳定的排序,我怀疑最好的情况可能是O(n*log n*m),其中有
m
插入,因为您必须处理重叠。我尝试实现您的想法,并将其包含在我的答案中。它看起来像你想的那样吗?插入实际上不是O(1),它是O(插入次数),由于长度检查,我认为
ToString
的O也太低了,因为至少你是通过idx有效排序的,这将使它成为O(n logn)你是对的。您可以放弃insert上的长度检查,并插入
ToString
,使其成为O(1)。即使检查结果是O(插入),它还是非常有效的。我很确定
string.Length
是O(1)。有一个递归步骤,你把所有长度加起来,使长度为O(n.insertions)。你是对的,它是O(插入),但是因为
string.Length
是O(1),所以它非常便宜。
type InsertList = IL of (int * string) list 

// Insert string 'str' at the specified index 
let insertAt idx str (IL items) = IL (idx, str)::items

// Create insert list from a string
let ofString str = IL [str]