我有下面的F#代码,它可以连接4个字符串,用空格分隔,只包括那些不是null或完全是空格的字符串。
let street =
split.[5..8]
|> Array.filter (String.IsNullOrWhiteSpace >> not)
|> String.concat " "
这非常有效,但效果不如下面的C#实现。
var street = "";
if (!string.IsNullOrWhiteSpace(items[5]))
street += items[5];
if (!string.IsNullOrWhiteSpace(items[6]))
street += string.IsNullOrWhiteSpace(street) ? items[6] : " " + items[6];
if (!string.IsNullOrWhiteSpace(items[7]))
street += string.IsNullOrWhiteSpace(street) ? items[7] : " " + items[7];
if (!string.IsNullOrWhiteSpace(items[8]))
street += string.IsNullOrWhiteSpace(street) ? items[8] : " " + items[8];
return street;
有没有办法可以在F#中实现相同的实现方式,而不是使用内联函数?
答案 0 :(得分:5)
这是一个删除显式迭代和下标的变体,可以通过传入序列而不是直接引用split来修改为适用于seq的任何集合。
let otherStreet =
let combine (sb:StringBuilder) (s:String) =
if sb.Length = 0 then
sb.Append s
else
(sb.Append " ").Append s
split.[5..8]
|> Seq.filter (String.IsNullOrWhiteSpace >> not)
|> Seq.fold combine (StringBuilder())
|> (fun sb -> sb.ToString())
任何时候我需要从序列中积累结果我倾向于使用折叠而不是显式循环。代码中可能存在拼写错误和/或思考,因为我没有编译器方便验证它。我还打赌这个版本的执行情况比你的实现差一些,但它可以很容易地与非索引集合一起使用作为权衡。
答案 1 :(得分:1)
感谢@Gustavo建议使用StringBuilder:)
let otherStreet =
let sb = new StringBuilder()
for i = 5 to 8 do
if not (String.IsNullOrWhiteSpace split.[i]) then
if sb.Length = 0 then
sb.Append split.[i] |> ignore
else
sb.Append " " |> ignore
sb.Append split.[i] |> ignore
sb.ToString()
答案 2 :(得分:0)
如果您只想遍历数组一次,那么这种方法可能对您有用:
let street = Array.fold (fun x y -> if white y then x elif x="" then x+y else x+" "+y) ""
street (split.[5..8])
其中'白色'代表' String.IsNullOrWhiteSpace'。