Nim: найти индекс элемента в seq на основе предиката

#seq #nim-lang

#seq #nim-lang

Вопрос:

Если у меня есть последовательность значений, как мне найти индекс элемента на основе функции предиката? Например, если бы у меня был следующий seq:

 let values = @["pie", "cake", "ice cream"]
 

Как мне найти индекс первого элемента с четырьмя символами? Я знаю find , но, похоже, он находит индекс только по равенству и не позволяет передавать предикат. Я мог бы реализовать это сам, но кажется, что он должен быть в стандартной библиотеке, если find есть.

Ответ №1:

Простым решением было бы использовать map from sequtils для сопоставления предиката с входной последовательностью, а затем использовать find для получения индекса первого true значения в результате. Это возвращает -1, когда ни один элемент последовательности не удовлетворяет предикату:

 import sequtils

proc isLen4(s: string): bool =
  len(s) == 4

echo map(@["pie", "cake", "ice cream"], isLen4).find(true)  #--> 1
 

Это работает, но плохо для больших последовательностей, поскольку map обрабатывает всю последовательность. Таким образом, даже когда первый элемент удовлетворяет предикату, обрабатывается вся последовательность. Было бы лучше просто написать findIf процедуру, которая возвращает текущий индекс, когда выполняется предикат, вместо того, чтобы продолжать обрабатывать остальные входные данные:

 proc findIf[T](s: seq[T], pred: proc(x: T): bool): int =
  result = -1  # return -1 if no items satisfy the predicate
  for i, x in s:
    if pred(x):
      result = i
      break

echo @["pie", "cake", "ice cream"].findIf(isLen4)  #--> 1
 

Комментарии:

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

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