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

时间:2011-12-01 03:01:31

标签: f# stringbuilder

我正在寻找StringBuilder或同等功能的功能(如in,non-imperative)实现。我已经看到了几个功能数组实现,但它们本身不支持插入。开源,非(L?A?)GPL的奖金,F#的奖金,但如果需要,我可以从Haskell / OCaml / SML翻译。

欢迎使用算法的建议。

2 个答案:

答案 0 :(得分:3)

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

顺便提一下,System.String已经符合(我能做到的)你的描述:它是不可变的,支持连接,insertionMSDNremovalMSDN

更新

托马斯的想法引起了我的兴趣。采纳他的想法,这就是我想出来的

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)

用法

let bldr = 
  StringBuilder.create "abcdef"
  |> StringBuilder.insert 1 "xyz"
  |> StringBuilder.append "123"
  |> StringBuilder.remove 1 2

bldr.ToString() //azbcdef123

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

答案 1 :(得分:0)

我不知道任何可以完全按照您的要求执行的实现。但是,我认为你不能在结果上获得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,因此数据结构仍然是纯粹的功能。