Erlang列出:index_of函数?

时间:2009-09-22 09:56:41

标签: erlang

我正在寻找一个Erlang库函数,它将返回列表中特定元素的索引。

所以,如果

X=[10,30,50,70]

然后

lists:index_of(30, X)

会返回1等,就像java.util.List的{​​{1}}方法一样。

Erlang标准库中是否存在这样的方法?我试着查看列表模块,但没有运气。或者我应该自己写一下吗?

感谢。

6 个答案:

答案 0 :(得分:21)

你必须自己定义,如下:

index_of(Item, List) -> index_of(Item, List, 1).

index_of(_, [], _)  -> not_found;
index_of(Item, [Item|_], Index) -> Index;
index_of(Item, [_|Tl], Index) -> index_of(Item, Tl, Index+1).

但请注意,访问列表的第N个元素是O(N),因此通常按索引访问列表的算法效率低于按顺序遍历列表的算法。

答案 1 :(得分:15)

正如其他人所指出的,有更有效的方法来解决这个问题。但如果你正在寻找快速的东西,这对我有用:

string:str(List, [Element]).

答案 2 :(得分:3)

其他解决方案(注意这些是base-index = 1):

index_of(Value, List) ->
   Map = lists:zip(List, lists:seq(1, length(List))),
   case lists:keyfind(Value, 1, Map) of
      {Value, Index} -> Index;
      false -> notfound
   end.

index_of(Value, List) ->
   Map = lists:zip(List, lists:seq(1, length(List))),
   case dict:find(Value, dict:from_list(Map)) of
      {ok, Index} -> Index;
      error -> notfound
   end.

在某些时候,当您传递给这些函数的列表足够长时,构建附加列表或字典的开销变得过于昂贵。如果每次想要通过将列表保持在这些函数之外的列表中来搜索列表时可以避免进行构造,则可以消除大部分开销。

使用字典会散列列表中的值并帮助将索引查找时间缩短为O(log N),因此最好将其用于大型单键列表。

通常,程序员可以将数据组织到适合您使用它们的结构中。我的猜测是没有内置的index_of是为了鼓励这样的考虑。如果您正在进行单键查找 - 这实际上是index_of() - 使用字典。如果您正在进行多键查找,请使用带有列表的元组列表:keyfind()等。如果您的列表非常大,那么解决方案可能最简单。

答案 3 :(得分:1)

这个函数对于Erlang来说非常罕见,这可能是它不在标准库中的原因。没有经验丰富的Erlang程序员需要它,并且不鼓励使用使用此功能的算法。当有人需要它时,可以为自己的目的写作,但这种非常罕见的情况并不是将其包括在stdlib中的理由。以适当的方式设计您的数据结构,而不是要求此功能。在大多数情况下,需要此功能表示设计错误。

答案 4 :(得分:-1)

我认为作者提出了一个有效的案例。这是我在日志记录应用程序中的用例。目标是针对针对各种级别的错误响应执行的操作来检查错误的严重性。

get_index(A,L) ->
    get_index(A,L,1).
get_index(A,[A|_],N) ->
    N;
get_index(A,[_|T],N) ->
    get_index(A,T,N+1).

get_severity(A) ->
    Severity=[debug,info,warn,error],
    get_index(A,Severity).

答案 5 :(得分:-1)

以下函数返回列表中给定元素的索引列表。结果可用于获取列表中重复元素的第一个或最后一个匹配项的索引。

indices_of(Element, L) ->                                                                                                                                                          
    Indices = lists:zip(lists:seq(1,length(L)), L),                                                                                                                                
    [ I || {I, E} <- Indices, E == Element ].