6

簡単な例として、数値のリストがあり、L特定の数値よりも大きい最初の要素を見つけたいとしますX。私はこのようなリスト内包でこれを行うことができます:

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

しかし、リストが非常に長く、最初の一致が早い可能性があるため、これは潜在的に非常に非効率的であるように思われます。だから私はどちらかを疑問に思っていますa)最初の一致が見つかった後にリスト内の残りの要素を評価しないこれを行うための効率的な方法はありますか?または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 */
}
4

3 に答える 3

15

まあ、のようなもの

firstmatch(YourList, Number) -> 
   case lists:dropwhile(fun(X) -> X =< Number end, YourList) of
     [] -> no_solution;
     [X | _] -> X
   end.
于 2012-09-30T01:17:02.527 に答える
4

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

-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.
于 2012-09-29T23:37:40.607 に答える
4

簡単な解決策は次のとおりです。

first_greater([],_) -> undefined;
first_greater([H|_], Num) when H > Num -> H;
first_greater([_|T], Num) -> first_greater(T,Num).
于 2012-09-30T09:16:57.467 に答える