在F#中切片/分组相同字符的序列 [英] Slice/Group a sequence of equal chars in F#

查看:143
本文介绍了在F#中切片/分组相同字符的序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



例如:
字符串aaaBbbcccccccDaBBBzcc11211

/ code>应该转换为一个字符串列表,如
[aaa;B;bb;ccccccc;D;a; BBB;z;cc;11;2;11] 这是我的解决方案直到现在:

 让groupSequences(text:string)= 

让toString chars =
System.String(chars |> Array.ofList)

让rec groupSequences递归acc chars = seq {
match(acc,chars)with
| [],c :: rest - >
收益! groupSequencesRecursive [c] rest
| _,c :: rest当acc。[0] <> c - >
收益率(toString acc)
收益率! groupSequencesRecursive [c] rest
| _,c :: rest当acc。[0] = c - >
收益! groupSequencesRecursive(c :: acc)rest
| _,[] - >
收益率(toString acc)
| _ - >
yield
}

text
|> List.ofSeq
|> groupSequencesRecursive []

groupSequencesaaaBbbcccccccDaBBBzcc11211
|> Seq.iter(fun x - > printfn%sx)
|>忽略

我是F#新手。

这个解决方案可以更好吗?

解决方案


$ b

 让组xs = 
让文件夹x =函数
| [] - > [[x]]
| (h :: t):: ta当h = x时 - > (x :: h :: t):: ta
| acc - > [x] :: acc
Seq.foldBack文件夹xs []

这个函数有键入 seq<'a> - > '列表列表,当'a:equal 时,不仅适用于字符串,而且适用于任何(有限)的元素序列,只要元素类型支持相等比较。
$ b

与OP中的输入字符串一起使用时,返回值与预期形状中的 不同:

 > aaaBbbcccccccDaBBBzcc11211;; 
val it:char list list =
[['a'; '一个'; '一个']; [ B]; [ B; B]; ['C'; 'C'; 'C'; 'C'; 'C'; 'C'; 'C'];
['D']; ['一个']; [ B; B; B]; [ Z]; ['C'; 'C']; [ 1’ ; 1’ ]; [ 2’ ];
['1'; '1']]

代替字符串列表,返回值是 char列表。您可以使用 map 轻松将其转换为字符串列表:

 >组aaaBbbcccccccDaBBBzcc11211|> List.map(List.toArray>> System.String);; 
val it:System.String list =
[aaa; B; BB; CCCCCCC; d; 一个; BBB; Z; CC; 11; 2; 11]

这利用了 String 构造函数重载,它需要一个 char [] 作为输入。



如前所述,所以也可以与其他类型的列表一起使用;例如整数:

 >组[1; 1; 2; 2; 2; 3; 4; 4; 3; 3; 3; 0] ;; 
val it:int list list = [[1; 1]; [2; 2; 2]; [3]; [4; 4]; [3; 3; 3]; [0]]


I need to extract the sequence of equal chars in a text.

For example: The string "aaaBbbcccccccDaBBBzcc11211" should be converted to a list of strings like ["aaa";"B";"bb";"ccccccc";"D";"a";"BBB";"z";"cc";"11";"2";"11"].

That's my solution until now:

let groupSequences (text:string) = 

    let toString chars =
        System.String(chars |> Array.ofList)

    let rec groupSequencesRecursive acc chars = seq {
        match (acc, chars) with
        | [], c :: rest -> 
            yield! groupSequencesRecursive [c] rest
        | _, c :: rest when acc.[0] <> c -> 
            yield (toString acc)
            yield! groupSequencesRecursive [c] rest
        | _, c :: rest when acc.[0] = c -> 
            yield! groupSequencesRecursive (c :: acc) rest
        | _, [] -> 
            yield (toString acc)
        | _ -> 
            yield ""
    }

    text
    |> List.ofSeq
    |> groupSequencesRecursive []

groupSequences "aaaBbbcccccccDaBBBzcc11211"
|> Seq.iter (fun x -> printfn "%s" x)
|> ignore

I'm a F# newbie.

This solution can be better?

解决方案

Here a completely generic implementation:

let group xs =
    let folder x = function
        | [] -> [[x]]
        | (h::t)::ta when h = x -> (x::h::t)::ta
        | acc -> [x]::acc
    Seq.foldBack folder xs []

This function has the type seq<'a> -> 'a list list when 'a : equality, so works not only on strings, but on any (finite) sequence of elements, as long as the element type supports equality comparison.

Used with the input string in the OP, the return value isn't quite in the expected shape:

> group "aaaBbbcccccccDaBBBzcc11211";;
val it : char list list =
  [['a'; 'a'; 'a']; ['B']; ['b'; 'b']; ['c'; 'c'; 'c'; 'c'; 'c'; 'c'; 'c'];
   ['D']; ['a']; ['B'; 'B'; 'B']; ['z']; ['c'; 'c']; ['1'; '1']; ['2'];
   ['1'; '1']]

Instead of a string list, the return value is a char list list. You can easily convert it to a list of strings using a map:

> group "aaaBbbcccccccDaBBBzcc11211" |> List.map (List.toArray >> System.String);;
val it : System.String list =
  ["aaa"; "B"; "bb"; "ccccccc"; "D"; "a"; "BBB"; "z"; "cc"; "11"; "2"; "11"]

This takes advantage of the String constructor overload that takes a char[] as input.

As initially stated, this implementation is generic, so can also be used with other types of lists; e.g. integers:

> group [1;1;2;2;2;3;4;4;3;3;3;0];;
val it : int list list = [[1; 1]; [2; 2; 2]; [3]; [4; 4]; [3; 3; 3]; [0]]

这篇关于在F#中切片/分组相同字符的序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆