Подтвердить что ты не робот

Списки Erlang: функция index_of?

Я ищу библиотечную функцию Erlang, которая вернет индекс определенного элемента в списке.

Итак, если

X=[10,30,50,70]

затем

lists:index_of(30, X)

будет возвращать 1 и т.д., как метод java.util.List indexOf().

Существует ли такой метод в стандартной библиотеке Erlang? Я попробовал посмотреть в модуле списков, но не повезло. Или я должен написать сам?

Спасибо.

4b9b3361

Ответ 1

Вам нужно будет определить его самостоятельно, например:

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), поэтому алгоритм, который часто обращается к списку по индексу, будет менее эффективным, чем тот, который последовательно выполняет итерацию.

Ответ 2

Как отмечали другие, для этого существуют более эффективные способы решения. Но если вы ищете что-то быстрое, это сработало для меня:

string:str(List, [Element]).

Ответ 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.

В какой-то момент, когда списки, которые вы передаете этим функциям, становятся достаточно длинными, накладные расходы на создание дополнительного списка или dict становятся слишком дорогими. Если вы не можете выполнять конструкцию каждый раз, когда хотите выполнить поиск в списке, сохранив список в этом формате вне этих функций, вы устраните большую часть накладных расходов.

Использование словаря приведет к хешированию значений в списке и поможет уменьшить время поиска индекса до O (log N), поэтому лучше использовать его для больших списков с однократной записью.

В общем, вам, программисту, организовать ваши данные в структурах, которые соответствуют тому, как вы собираетесь их использовать. Я предполагаю, что отсутствие встроенного index_of должно поощрять такое рассмотрение. Если вы делаете однократные запросы - это действительно то, что index_of() - использовать словарь. Если вы выполняете многопользовательский поиск, используйте список кортежей со списками: keyfind() et al. Если ваши списки слишком велики, возможно, менее простое решение. Лучше всего.

Ответ 4

Эта функция очень необычна для Erlang, и это может быть причиной того, что она не находится в стандартной библиотеке. Ни один из опытных программистов Erlang не нуждается в этом, и не рекомендуется использовать алгоритмы, используя эту функцию. Когда кому-то это нужно, вы можете писать для своих целей, но это очень редкие случаи не являются основанием для включения его в stdlib. Правильно спроектируйте свои структуры данных, а не задавайте эту функцию. В большинстве случаев эта функция указывает на ошибку в дизайне.

Ответ 5

гораздо проще:

index_of(Elem, List) ->
    {Map, _} = lists:mapfoldr(fun(X, I) -> {{X, I}, I + 1} end, 0, List),
    {_, Index} = lists:keyfind(Elem, 1, Map), Index.

Ответ 6

Я думаю, что автор делает правильный пример. Вот мой прецедент из приложения регистрации. Цель состоит в том, чтобы проверить степень серьезности ошибки в отношении действий, которые должны выполняться против различных уровней ответа на ошибку.

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).

Ответ 7

Следующая функция возвращает список индексов данного элемента в списке. Результат может быть использован для получения индекса первого или последнего вхождения дубликата в списке.

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