電子メール アドレスのリストがあり、各アドレスに電子メール通知を送信する必要があります。一度に 25 個のアドレスのブロックでこれを行いたいと思います。F# のような関数型言語で、25 個の電子メール アドレスをまとめて "折りたたむ" (連結する) 簡単な方法はありますか?それぞれがセミコロンで区切られています。.NET に String.Split メソッドがあることは知っていますが、一度に 25 個を連結する必要があります。
F# でこれを実行する最もエレガントな方法は何ですか?
電子メール アドレスのリストがあり、各アドレスに電子メール通知を送信する必要があります。一度に 25 個のアドレスのブロックでこれを行いたいと思います。F# のような関数型言語で、25 個の電子メール アドレスをまとめて "折りたたむ" (連結する) 簡単な方法はありますか?それぞれがセミコロンで区切られています。.NET に String.Split メソッドがあることは知っていますが、一度に 25 個を連結する必要があります。
F# でこれを実行する最もエレガントな方法は何ですか?
これがまだ関連している場合は、区切り文字を使用して配列に変換せずに一連の文字列を結合する関数を次に示します。
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()
最大で 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%i@example.com" i]
allMails
|> Break 5
|> Seq.map (fun arr -> System.String.Join(";", arr))
|> Seq.iter Sendmail
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 スライスも参照してください。
あまりきれいではありませんが、機能します:
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))