2015-02-24 3 views
0

Я пытаюсь найти способ получить индекс элемента в массиве, который частично соответствует определенному patten. Скажем, у меня есть массив со значениямиИндекс элемента в массиве в Perl

Maria likes tomatoes, 
Sonia likes plums, 
Andrew likes oranges 

Если мой термин поиска сливами, я буду получать 1 возвращается в качестве индекса. Спасибо!

+0

Итерации по массиву и использование соответствия шаблону, чтобы найти, соответствует ли ваша строка. – Jens

ответ

3

Быстрый поиск не нашел обмана, но я уверен, что есть один. Между тем:

Чтобы найти элементы массива, удовлетворяющие определенному условию, вы используете grep. Если вы хотите индексы вместо элементов ... ну, то Perl 6 добавил метод grep-index для обработки этого случая, но в Perl 5 самым простым способом является изменение цели grep. То есть вместо того, чтобы запускать его в исходном массиве, запустите его в списке индексов - просто с условием, которое ссылается на исходный массив. В вашем случае, это может выглядеть следующим образом:

my @array = ('Maria likes tomatoes', 
       'Sonia likes plums', 
       'Andrew likes oranges'); 

grep { $array[$_] =~ /plums/ } 0..$#array; # 1 

Соответствующие биты:

  • $#array возвращает индекс последнего элемента @array.
  • м..п генерирует диапазон значений между м и п (включительно); в контексте списка, который становится списком этих значений.
  • grep {код}список возвращает элементы списка , для которых код производит истинное значение, когда специальная переменная $_ устанавливается на элемент.

Эти виды выражений наиболее легко читаются справа налево. Итак, сначала мы сгенерируем список всех индексов исходного массива (0..$#array), затем мы используем grep для циклического преобразования этих индексов и для каждого индекса (представленного $_), см., Соответствует ли соответствующий элемент ($array[$_]) ~=) обычное выражение /plums/.

Если да, то этот индекс возвращается grep; если нет, это не учтено, поэтому конечным результатом является список только тех индексов, для которых условие истинно. В этом случае, этот список содержит только значение 1.

Добавлена ​​ответить на ваш комментарий: Важно отметить, что возвращаемое значение grep, как правило, список совпадающих элементов, даже если есть только один матч. Если вы назначаете результат массиву (например, с my @indexes = grep ...), массив будет содержать все соответствующие значения. Однако grep является контекстно-зависимым, и если вы вызываете его в скалярном контексте (например, назначая его возвращаемое значение скалярной переменной с чем-то вроде my $count = grep ...), вместо этого вы получите только номер, указывающий, сколько совпадений там мы. Вы можете взглянуть на this tutorial на чувствительность контекста в Perl.

+0

Спасибо, Марк! Хотя при печати я получаю правильное значение с помощью этого кода, я не могу его сохранить. Если я назначу его переменной, я получаю 1 в результате, независимо от индекса. Знаете ли вы, какая проблема здесь? – Newyork111

+0

grep будет возвращать список, поэтому, если у вас есть несколько обращений, вы получите несколько результатов. Вы можете назначить его с помощью 'my @indicies = grep ....'. – Sobrique

+0

@ Newyork111 - см. Мое редактирование. –

3

Это то, что firstidx от List::MoreUtils для.

#!/usr/bin/perl 

use strict; 
use warnings; 
use 5.010; 

use List::MoreUtils 'firstidx'; 

my @array = ('Maria likes tomatoes', 
      'Sonia likes plums', 
      'Andrew likes oranges'); 

say firstidx { /plums/ } @array; 

Update: Я вижу, что draegtun ответил комментарий о получении нескольких индексов. Но мне интересно, почему вы не могли просто просмотреть документацию List :: MoreUtils, чтобы увидеть, есть ли там полезная функция.

+0

Что делать, если вам нужны индексы всех соответствующих элементов, а не только первый (или последний, поскольку 'List :: MoreUtils' также предлагает' lastidx')? –

+2

@MarkReed - см. 'Indexes' в' List :: MoreUtils' для получения индексов всех соответствующих элементов - https://metacpan.org/pod/List::MoreUtils#indexes-BLOCK -LIST – draegtun

Смежные вопросы