如何计算字符串中特定字符的出现次数

时间:2016-10-13 13:47:14

标签: f#

我不知道从哪里开始检查字符串是否出现n个特定字符。我已经列出了我认为是函数框架但我不确定的内容的基本概要?

{{1}}

4 个答案:

答案 0 :(得分:11)

<强> TL; DR

“最惯用”的方式可能是@Mark Seemanns:

let count x = Seq.filter ((=) x) >> Seq.length

T oo L ong部分

请注意,此函数完全通用:x:'a -> (seq<'a> -> int) when 'a : equality,即只要x支持相等,它就会计算'a s序列中任何'a的出现次数。由于右侧是函数,我们也不需要指定字符串参数。这称为point-free样式。 该函数是通过将=运算符包含在括号中(想象(=) = fun x y -> x = y),使用此谓词过滤序列并计算结果{{1}来构建的。长度,即

seq

let count x xs =
    xs
    |> Seq.filter (fun x' -> x' = x)
    |> Seq.length

当然你也可以利用'C#方式':

let count x xs =
    Seq.length(Seq.filter (fun x' -> x' = x) xs)

在这里,您不能只将等于运算符let count' x xs = System.Linq.Enumerable.Count(xs, fun x' -> x' = x) 转换为谓词,因为F#编译器需要做一些魔术才能将F#(=)转换为'a -> bool

用法完全相同:

Func<'a, bool>

或(更具可读性)

count 'a' "abbbac"

这个(以及更好的可组合性)是功能程序员倾向于颠倒参数顺序的原因("abbbac" |> count 'a' "abbac" |> count' 'b' count x xs)。

更具异国情调(性能较差)的解决方案:

count xs x

答案 1 :(得分:3)

这是一个尾递归循环版本。

let countCharFromNth (getStr : string)(chkdChar : char) = 
    let rec loop i count =
        if i < getStr.Length then 
            if getStr.[i] = chkdChar then loop (i+1) (count+1)
            else loop (i+1) count
        else count
    loop 0 0

编译器会将其转换为命令循环,因为所有函数调用都在尾(最后)位置。虽然比其他版本更长,但这是最高效的方式,因为它不会创建不必要的中间集合。

答案 2 :(得分:3)

使用折叠是另一种选择:

open System

let countCharFold targetChar = 
  Seq.fold (fun count ch -> if ch = targetChar then count + 1 else count) 0

[<EntryPoint>]
let main argv = 
  let text = "hello world"
  let ch = 'l'
  printfn "%d" (countCharFold ch text)

  Console.ReadLine() |> ignore
  0

答案 3 :(得分:0)

要提供另一个可能更注重功能的解决方案,我尝试将建议的答案更改为与内部循环匹配的模式:

public function index()
{
    $inscrit = Inscrit::all();
    return view('index', compact('inscrit'));
}

public function store(Request $request)
{
    $storeData = $request->validate([
        'INS_CIVILITE' => 'max:15',
        'INS_NOM' => 'max:50',
        'INS_PREN' => 'max:50',
        'INS_NUM_RUE' => 'max:8',
        'INS_TEL1' => 'max:10',
        'INS_TEL2' => 'max:10',
        'INS_AGE' => 'numeric',
        'INS_OBS' => 'max:255',
        'INS_Rue' => 'max:255',
        'INS_DATE' => 'max:255',
        'INS_NAISS' => 'max:255',
    ]);
    $inscrit = Inscrit::create($storeData);

    return redirect('/inscrits')->with('completed', 'Nouvel inscrit !');
}

public function show($id = 0)
{
    $data = Inscrit::where('INS_ID', $id)->first();
    return response()->json($data);
}

    public function edit($id)
{
    $inscrit = Inscrit::findOrFail($id);
    return view('index', compact('inscrit'));
}

public function update(Request $request, $id)
{
    $updateData = $request->validate([
        'INS_CIVILITE' => 'max:15',
        'INS_NOM' => 'max:50',
        'INS_PREN' => 'max:50',
        'INS_NUM_RUE' => 'max:8',
        'INS_TEL1' => 'max:10',
        'INS_TEL2' => 'max:10',
        'INS_AGE' => 'numeric',
        'INS_OBS' => 'max:255',
        'INS_Rue' => 'max:255',
        'INS_DATE' => 'max:255',
        'INS_NAISS' => 'max:255',
    ]);
    $id = request()->input('INS_EID');
    Inscrit::where('INS_ID', $id)->update($updateData);
    return redirect('/inscrits')->with('completed', 'inscrit mis à jour');
}

public function destroy($id)
{
    $id = request()->input('INS_ID');
    $inscrit = Inscrit::where('INS_ID', $id)->delete();

    return redirect('/inscrits')->with('completed', 'inscrit supprimé');
} 

我将模式匹配与when情况本质上模拟了if / else结构,并在迭代器超出范围时使用了结束循环的快捷方式。

此版本还允许将let charCountFrom str i chr = let rec loop = function | (it, count) when (String.length str) = it -> count | (it, count) when str.[it] = chr -> loop (it+1, count+1) | (it, count) -> loop (it+1, count) loop (i,0) 指定为计数的起始索引,但是可以通过将i的出现次数替换为0来轻松删除它。

如果需要的话,对参数进行重新排序也可以进行计算。