18

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

因此,如果

X = [10,30,50,70]
lists:index_of(30, X)

将返回 1 等,就像java.util.List'indexOf()方法一样。

Erlang标准库中是否存在这种方法?我尝试查看列表模块,但没有运气。还是我自己写?

4

6 回答 6

22

您必须自己定义它,如下所示:

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),因此经常按索引访问列表的算法效率低于按顺序遍历列表的算法。

于 2009-09-22T10:10:47.943 回答
15

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

string:str(List, [Element]).
于 2011-07-20T12:50:55.437 回答
5

其他解决方案(注意这些是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() 等。如果您的列表非常大,那么最好采用不那么简单的解决方案。

于 2010-11-10T02:34:26.593 回答
1

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

于 2009-09-22T18:44:27.717 回答
-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).
于 2012-11-10T06:00:13.203 回答
-1

以下函数返回列表中给定元素的索引列表。Result 可用于获取列表中第一次或最后一次出现重复元素的索引。

indices_of(Element, L) ->                                                                                                                                                          
    Indices = lists:zip(lists:seq(1,length(L)), L),                                                                                                                                
    [ I || {I, E} <- Indices, E == Element ].   
于 2017-02-25T20:40:15.613 回答