2009-01-14 71 views
1

我有一個電子郵件地址列表,我需要向每個地址發送電子郵件通知。我想一次以25個地址爲單位進行此操作。有沒有像F#這樣的函數式語言的快速方法,可以將25個電子郵件地址「拼接」(連接)在一起,每個地址都用分號分隔。我知道.NET中有String.Split方法,但我需要一次連接25個。F# - 按時間間隔將列表拆分爲連續字符串

在F#中執行此操作的最優雅方式是什麼?

+0

這可能需要我花一些時間來消化這些,我仍然圍繞着F#。 我不知道在C#或F#中執行此操作的最簡單方法是: 1)將所有電子郵件都轉換爲一個大字符串。但每25封電子郵件使用;;代替 ;作爲分隔符 2)然後使用;;做一個String.Split。 想法? – BuddyJoe 2009-01-15 01:49:03

回答

0

它並不過分漂亮,但它的工作原理:

let breakWords separator groupSize (input : string) = 
    let words = input.Split([| separator |]) 
    let arraySize = words.Length/groupSize + (if words.Length % groupSize > 0 then 1 else 0) 
    let groups = Array.init arraySize (fun index -> 
     let startIndex = index * groupSize 
     let endIndex = Math.Min(startIndex + groupSize - 1, words.Length - 1) 
     words.[startIndex .. endIndex]) 
    groups |> Seq.map (fun x -> String.Join(";", x)) 
1

這裏打入組最多N次的方式:

// break a sequence up into a sequence of arrays, 
// each of length at most 'n' 
let Break n (s:seq<_>) = 
    seq { 
     use e = s.GetEnumerator() 
     while e.MoveNext() do 
      let i = ref 0 
      yield [| 
       yield e.Current 
       i := !i + 1 
       while !i < n && e.MoveNext() do    
        yield e.Current 
        i := !i + 1 |] } 

,然後你的解決方案就是像

let Sendmail addr = printf "%A\n\n" addr 
let allMails = [for i in 1..25 -> sprintf "a%[email protected]" i] 
allMails 
|> Break 5 
|> Seq.map (fun arr -> System.String.Join(";", arr)) 
|> Seq.iter Sendmail 
0

Seq模塊有一個窗口函數,但它給了你一個滑動窗口,所以對這個問題沒有好處。

這裏是我的版本,我沒有測試性能與其他答案如何比較,但它的漂亮(我想!)

//Add an "extension function" to the Seq module 
module Seq = 
    let rec chunks n (s:#seq<_>) = 
     seq { 
       if Seq.length s <= n then 
        yield s 
       else 
        yield Seq.take n s 
        yield! chunks n (Seq.skip n s)   
      } 

//Make curried version of String.Join 
let join sep (s:#seq<string>) = System.String.Join(sep, Array.of_seq s) 

//Compose the bits together 
let mailMerge n = Seq.chunks n >> Seq.map (join ";") 

//Test 
mailList |> mailMerge 25 

也許你可以看一下Array slices了。

1

如果這仍然是相關的,這裏是一個函數來加入一個字符串序列使用分隔符,但沒有轉換爲數組。

open System 
open System.Text 

/// Join a sequence of strings using a delimiter. 
/// Equivalent to String.Join() but without arrays. 
let join (items : seq<string>) (delim : string) = 
    // Collect the result in the string builder buffer 
    // The end-sequence will be "item1,delim,...itemN,delim" 
    let buff = 
     Seq.fold 
      (fun (buff :StringBuilder) (s:string) -> buff.Append(s).Append(delim)) 
      (new StringBuilder()) 
      items 

    // We don't want the last delim in the result buffer, remove 
    buff.Remove(buff.Length-delim.Length, delim.Length).ToString()