2011-11-30 36 views
8

Dường như không có chức năng nào trong thư viện chuẩn loại char -> string -> string, chèn char trước (hoặc ở cuối) string. Có cách giải quyết, ví dụ: bằng cách sử dụng String.make hoặc String.blit. Có một cách thanh lịch để làm điều này?Làm thế nào để bạn thêm một char vào một chuỗi trong OCaml?

+1

Sử dụng 'Bộ đệm' có thể phù hợp hơn để phát triển chuỗi. –

Trả lời

6

String.makeString.blit là một cách hay để làm như vậy, nhưng chúng dường như là bắt buộc. Cá nhân tôi thích để làm cho chức năng ghi vào sử dụng Char.escaped và nối chuỗi:

let (^$) c s = s^Char.escaped c (* append *) 
let ($^) c s = Char.escaped c^s (* prepend *) 
+7

Tôi sẽ nói 'Char.escaped' là dành cho các ứng dụng chuyên biệt như tạo mã OCaml làm đầu ra hoặc viết các thông điệp có thể đọc được của con người. Đối với các trường hợp thông thường, 'String.make 1 c' có lẽ là những gì bạn muốn. Nó có vẻ hơi vụng về. Pin có 'BatString.of_char'. –

+0

Cảm ơn bạn đã làm rõ về 'Char.escaped'. Tôi giữ câu trả lời không thay đổi để người khác biết về nó. – pad

+1

Tại sao lại giảm xuống khi mọi thứ được làm rõ từ câu trả lời và nhận xét của @ JeffreyScofield? – pad

16

Mã từ @pad là những gì tôi sẽ sử dụng, vì tôi thích để điều trị chuỗi như bất biến nếu có thể. Nhưng tôi sẽ không sử dụng Char.escaped; nó đặc biệt khi bạn muốn biểu diễn từ vựng OCaml của một nhân vật. Vì vậy, đây là những gì bạn nhận được nếu bạn thực hiện sự thay đổi:

let prefix_char s c = String.make 1 c^s 

let suffix_char s c = s^String.make 1 c 
8

tôi đã thực hiện một sự so sánh của tính hiệu quả của phương pháp tiếp cận khác nhau:

  1. Tôi đã viết một bài kiểm tra đơn giản:

    let append_escaped s c = s^Char.escaped c 
    let append_make s c = s^String.make 1 c 
    let append_sprintf s c = Printf.sprintf "%s%c" s c 
    
    let _ = 
        let s = "some text" in 
        let c = 'a' in 
        for i = 1 to 100000000 do 
        let _ = append_(*escaped|make|sprintf*) s c in() 
        done 
    
  2. Tôi biên dịch nó một cách tự nhiên (Intel Core 2 Duo).

  3. Tôi đã chạy thử nghiệm ba lần cho mỗi tùy chọn, định thời gian thử nghiệm với time và tính thời gian trung bình thực sự.

Dưới đây là kết quả:

  1. s^String.make 1 c: 7.75s (100%)

  2. s^Char.escaped c: 8.30s (107%)

  3. Printf.sprintf "%s%c" s c : 68.57s (885%)

+2

Chỉ cần lưu ý, một lần nữa: 'Char.escaped' không thực hiện tương tự như' String.make'. Nó tạo ra một giá trị "thoát" cho nhân vật, theo các quy tắc từ vựng của OCaml. Để thấy điều này, hãy thử thêm một dòng mới (''\ n'') theo cách này. Đó cũng là lý do tại sao nó chậm hơn một chút. Đối với hầu hết các mục đích chung, bạn muốn sử dụng 'String.make 1 c'. Đương nhiên 'Printf.sprintf' chậm hơn rất nhiều, nhưng cực kỳ linh hoạt. –

+0

@JeffreyScofield Tôi sẽ chỉ thêm phần này, vì vậy mọi người không cần phải tự thử: 'Char.escaped '\ n'' =' "\\ n" '. –

+0

Cảm ơn, có lẽ tôi nên tự nói điều này! Những nhận xét này bị giới hạn rất ngắn. Dù sao đi nữa: 'Char.đã thoát '\ n'' cung cấp cho bạn chuỗi gồm hai ký tự bao gồm '' \\ '' và '' n''. 'String.make 1 '\ n'' cung cấp cho bạn chuỗi ký tự một gồm'' \ n'', có nhiều khả năng là thứ bạn muốn. –

Các vấn đề liên quan