2012-09-29 6 views
5

単純な例として、数字のリストがLで、特定の数よりも大きい最初の要素を探したいとしますXErlang:リスト内の最初の要素(条件の残りの部分を評価しない)

([email protected])24> L = [1, 2, 3, 4, 5, 6].    
[1,2,3,4,5,6] 
([email protected])25> X = 2.5. 
2.5 
([email protected])26> [First | _] = [E || E <- L, E > X]. 
[3,4,5,6] 
([email protected])27> First. 
3 

しかし、リストが非常に長くなる可能性があり、最初の試合は早い段階で可能性があるため、これは、潜在的に非常に非効率です:私はこのようなリストの内包表記でこれを行うことができます。だから、私は、どちらかが、最初の試合が見つかった後、リストの残りの要素を評価しない、これを行う効率的な方法があるかどうか、またはb)これがコンパイルされると、Erlangは残りの比較をとにかく最適化しますか?

これは私がCで探しているものを達成する方法を次のとおりです。

int first_match(int* list, int length_of_list, float x){ 
    unsigned int i; 
    for(i = 0; i < length_of_list, i++){ 
     if(x > list[i]){ return list[i]; } /* immediate return */ 
    } 
    return 0.0; /* default value */ 
} 

答えて

11

firstmatch(YourList, Number) -> 
    case lists:dropwhile(fun(X) -> X =< Number end, YourList) of 
    [] -> no_solution; 
    [X | _] -> X 
    end. 
+1

ニース。これは私の解決策よりも簡潔です。 'dropwhile'が実際に最初の失敗した試合の後に評価を停止することを確認するために、ちょっと見ていなければなりませんでした。私はあなたが関数として条件を指定できるように(ロジックを反転させることなく)関数をラップしました:https://gist.github.com/3807110 – dantswain

3

は、ここで私が思い付くことができたものです。私はまだ、より良い答えがあるかどうか、そして/または最も簡単なことが最適化されているかどうかを知りたいと思います(私はそれについてもっと考えています。

-module(lazy_first). 

-export([first/3]). 

first(L, Condition, Default) -> 
    first(L, [], Condition, Default). 

first([E | Rest], Acc, Condition, Default) -> 
    case Condition(E) of 
    true -> E; 
    false -> first(Rest, [E | Acc], Condition, Default) 
    end; 

first([], _Acc, _Cond, Default) -> Default. 

例:

14> lazy_first:first([1, 2, 3, 4, 5], fun(E) -> E > 2.5 end, 0.0). 
3 
15> lazy_first:first([1, 2, 3, 4, 5], fun(E) -> E > 5.5 end, 0.0). 
0.0 

編集

ここでアキュムレータのないバージョンがあります。うまく

first([E | Rest], Condition, Default) -> 
    case Condition(E) of 
    true -> E; 
    false -> first(Rest, Condition, Default) 
    end; 

first([], _Cond, Default) -> Default. 
+2

は内蔵のショートカットがあるのか​​どうかの問題に対処することはできませんが、これは確かのように見えますあなたのアキュムレータを除いてあなた自身をロールする適切な方法は不要です。 – macintux

+0

本当に良い点:)それは実際にそれを少し単純化します。 – dantswain

3

のようなものは、ここでは簡単なソリューションです:

first_greater([],_) -> undefined; 
first_greater([H|_], Num) when H > Num -> H; 
first_greater([_|T], Num) -> first_greater(T,Num). 
関連する問題