簡體   English   中英

每個列表的Erlang

[英]Erlang for each list of lists

我想創建一個僅包含長度為1的“列表列表”元素的新列表。

我提供的代碼給出了異常錯誤:沒有匹配的功能子句。

lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).

我是erlang的新手,我很難找到另一種編寫這段代碼的方法。

有人可以給我一些建議嗎?

您可以匹配列表理解來自然地做到這一點:

[L || L = [_] <- ListOfLists]

例如:

1> LoL = [[a], [b,c], d, [e], [f,g]].
[[a],[b,c],d,[e],[f,g]]
2> [L || L = [_] <- LoL].
[[a],[e]]

如果您想要元素本身(作為結果[a, e]而不是[[a], [e]] ),則可以在形狀內的元素上進行匹配:

3> [L || [L] <- LoL].    
[a,e]

根據LoL中包含的列表的大小,匹配將比在每個成員上調用length/1快得多。 調用length/1 ,然后測試結果需要遍歷整個列表,返回一個值,然后對其進行測試。 這比檢查列表的第二個元素是否為終止符(換句話說,數據的“形狀”是否匹配)要大得多。

關於您上面的嘗試...

作為Erlang的新手,熟悉基本的功能列表操作可能會有所幫助。 它們在功能(和邏輯)編程中一遍又一遍地彈出,並且通常具有相同的名稱。 “地圖”,“折疊”,“過濾器”,“缺點”,“汽車”(“頭”或“ hd”或[X|_] ),“ cdr”(“尾巴”或“ tl”或[_|X] ),等等。

您最初的嘗試:

lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).

這是行不通的,因為foreach/2僅返回ok ,從不返回任何值。 當您要遍歷列表以獲取副作用 時才使用它,而不是因為要獲得返回值而使用它。 例如,如果我有一個聊天系統,則聊天室中有一個當前成員列表,而廣播消息實際上是將每個聊天消息發送給列表中的每個成員,我可能會這樣做:

-spec broadcast(list(), unicode:chardata()) -> ok.
broadcast(Users, Message) ->
    Forward = fun(User) -> send(User, Message) end,
    lists:foreach(Forward, Users).

實際上,我並不關心返回值,並且我們也不會更改“ Users或“ Message ”列表中的任何Message (請注意,這里我們使用匿名函數捕獲所需的相關狀態 -本質上是計算出Message值,因此我們可以將arity 1函數呈現給foreach/2的列表操作。這是lambda變得最有用的地方在Erlang與命名函數中。)

當您希望將列表作為輸入並返回單個匯總值(使用某些操作將列表中的所有值都滾動為一個)時,可以使用fold(幾乎總是想使用foldl/3 ) :

4> lists:foldl(fun(X, A) when length(X) =:= 1 -> [X|A]; (_, A) -> A end, [], LoL).
[[e],[a]]

細分為:

Single =
    fun
        (X, A) when length(X) =:= 1 -> [X|A];
        (_, A) -> [X|A]
    end,
ListOfSingles = lists:foldl(Single, [], LoL).

這是具有兩個子句的匿名函數。

寫一個我們可以做的另一種方式:

Single =
    fun(X, A) ->
        case length(X) of
            1 -> [X|A];
            _ -> A
        end
    end,

這是一個優先事項,可以選擇在foldl/3的調用中內聯作為匿名函數。

但是,您真正要執行的操作是過濾列表,並且有一個通用的列表函數叫做。 您提供了一個返回布爾值的測試函數-如果測試為true,則該元素將在輸出中出現,否則它將不會:

5> lists:filter(fun([X]) -> true; (_) -> false end, LoL).
[[a],[e]]

像以前一樣將lambda分解:

6> Single =
6>     fun([X]) -> true;
6>        (_)   -> false
6>     end.
#Fun<erl_eval.6.54118792>
7> lists:filter(Single, LoL).
[[a],[e]]

在這里,我們在匿名函數頭中匹配了元素的形狀。 這個過濾器幾乎完全等同於上面的列表理解(實際上唯一的區別是列表理解的底層實現-從語義上講它們是相同的)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM