2016-04-03 44 views
4

說我有一個巨大的文本〜500個字符存儲在一個字符串中,我怎麼能通過字符串循環,每次我遇到字符'a'時增加一個變量1?如何循環訪問Elixir中的每個字符?

+6

歡迎來到Stack Overflow!你是否試圖自己解決這個問題?如果是這樣,你究竟在哪裏卡住?總的來說,人們對「請爲我製作這些代碼」 - 請求(看起來像這樣)做出的反應不是很好,但是**做得很好**「我試過這個,現在我被卡住了,請幫助「 - 請求;-) – Carpetsmoker

+1

500個字符很小,不是很大。在500個字符處,很難找到檢查字符串的不好方法。 –

回答

7

我的代碼sugestion是:

countSubstring = fn(_, "") -> 0 
       (str, sub) -> length(String.split(str, sub)) - 1 end 

你可以叫使用IO.puts countSubstring.(str, "a")

+1

這很好,你能解釋一下這是如何工作的嗎?我不明白它是如何跟蹤參數中每個「」的計數。對不起,我不習慣Elixir這是我的第一個項目,語法對我來說不是很友好:S – frostmage

+0

雖然它不是最直觀的解決方案,但它表現非常出色,同時也處理多個字符。在我的答案中看到基準。 –

+0

查看https://learnxinyminutes.com/docs/elixir/以快速查看涉及匿名函數的語法。簡而言之,Elixir函數(包括匿名函數)可以定義多個簽名,被調用的版本基於模式匹配和/或門。第一個變體處理輸入子字符串爲空的情況。第二個處理其他用例 - String.split()返回一個列表,該列表的大小減1對應於子字符串的出現次數。希望有所幫助。 – Everett

12

我認爲有更容易理解的方法來這,可能只是罰款你。使用正則表達式:

Regex.scan(~r/a/, str) |> Enum.count 

或將串入它的Unicode字符,然後對計數:

str |> String.graphemes |> Enum.count(fn(c) -> c == "a" end) 

這些都不是很有效的方法,但對性能的影響可以忽略不計了(相對較小!)只有500個字符的字符串。

如果您需要更高效的方法,一個好的選擇是經常迭代使用遞歸,然後手動計算出現次數。雖然這種方法非常冗長,但它表現更好。

defmodule Recursive do 
    def count(str, <<c::utf8>>) do 
    do_count(str, c, 0) 
    end 

    defp do_count(<<>>, _, acc) do 
    acc 
    end 

    defp do_count(<<c::utf8, rest::binary>>, c, acc) do 
    do_count(rest, c, acc + 1) 
    end 

    defp do_count(<<_::utf8, rest::binary>>, c, acc) do 
    do_count(rest, c, acc) 
    end 
end 

最後,這裏是一個使用benchfella的基準,迄今爲止的方法。我還包括@DeboraMartins的「分割長度」解決方案,它比上面所有的小字符串都要好。對於較大的字符串,遞歸方法的差異可以忽略不計。

# 500 Characters 

split length   500000 5.90 µs/op 
recursive   100000 10.63 µs/op 
regex count   100000 24.35 µs/op 
graphemes count  10000 118.29 µs/op 


# 500.000 Characters 

split length   100 11150.59 µs/op 
recursive    100 12002.20 µs/op 
regex count    100 25313.40 µs/op 
graphemes count   10 218846.20 µs/op 
相關問題