Преобразование кода в Perl Sub, но не уверен, что я делаю это правильно - PullRequest
2 голосов
/ 13 июня 2010

Я работаю над вопросом, который я разместил ранее ( здесь ), и пытаюсь преобразовать ответ в подпункт, чтобы я мог использовать его несколько раз.Не уверен, что все сделано правильно, хотя.Кто-нибудь может предоставить лучшую или более чистую сабвуфер?

У меня большой опыт программирования, но мой основной язык - PHP.Очень печально знать, как выполнять на одном языке, но не в состоянии сделать это на другом.

sub search_for_key
{
    my ($args) = @_;

    foreach $row(@{$args->{search_ary}}){
        print "@$row[0] : @$row[1]\n";
    }

    my $thiskey = NULL;

    my @result = map { $args->{search_ary}[$_][0] }     # Get the 0th column...
        grep { @$args->{search_in} =~ /$args->{search_ary}[$_][1]/ } # ... of rows where the
            0 .. $#array;                               #     first row matches
        $thiskey = @result;

    print "\nReturning: " . $thiskey . "\n";
    return $thiskey;    
}

search_for_key({
    'search_ary' => $ref_cam_make, 
    'search_in' => 'Canon EOS Rebel XSi'
});

--- Редактировать ---

Из ответов на этот вопрос я покасоединили функцию ниже.Я новичок для Perl, поэтому я не очень понимаю синтаксис.Все, что я знаю, это то, что в этой строке grep выдается ошибка (не ссылка ARRAY в строке 26).

Поскольку я, кажется, не предоставил достаточно информации, я также упомяну, что:

Я вызываю эту функцию следующим образом (что может или не может быть правильно):

search_for_key({
    'search_ary' => $ref_cam_make, 
    'search_in' => 'Canon EOS Rebel XSi'
});

И $ ref_cam_make - это массив, который я собираю из таблицы базы данных, например:

$ref_cam_make = $sth->fetchall_arrayref;

И это в такой структуре (если я понял, как заставить ассоциативную выборку работать правильно, я бы хотел использовать ее вместо цифровых клавиш):

Reference Array
Associative
row[1][cam_make_id]: 13, row[1][name]: Sony

Numeric
row[1][0]: 13, row[1][1]: Sony
row[0][0]: 19, row[0][1]: Canon
row[2][0]: 25, row[2][1]: HP

sub search_for_key
{
    my ($args) = @_;

    foreach my $row(@{$args->{search_ary}}){
        print "@$row[0] : @$row[1]\n";
    }

    print grep { $args->{search_in} =~ @$args->{search_ary}[$_][1] } @$args->{search_ary};
}

Ответы [ 3 ]

5 голосов
/ 13 июня 2010

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

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

use strict;
use warnings;

demo_search_feature();

sub demo_search_feature {
    my @camera_brands = (
        { make => 'Canon', id => 19 },
        { make => 'Sony',  id => 13 },
        { make => 'HP',    id => 25 },
    );

    my @test_searches = (
        "Sony's Cyber-shot DSC-S600",
        "Canon cameras",
        "Sony HPX-32",
    );

    for my $ts (@test_searches){
        print $ts, "\n";
        my @hits = find_hits($ts, \@camera_brands);
        print '  => ', cb_stringify($_), "\n" for @hits;
    }
}

sub cb_stringify {
    my $cb = shift;
    return sprintf 'id=%d make=%s', $cb->{id}, $cb->{make};
}

sub find_hits {
    my ($search, $camera_brands) = @_;
    return grep { $search =~ $_->{make} } @$camera_brands;
}
4 голосов
/ 13 июня 2010

Весь этот саб действительно сбивает с толку, и я довольно обычный пользователь Perl. Вот несколько общих предложений.

  • Никогда не создавайте свой собственный undef - используйте undef, затем возвращайтесь внизу return $var // 'NULL'.
  • Никогда не делайте этого: foreach $row, потому что foreach my $row менее подвержен возникновению проблем. Локализация переменных - это хорошо.
  • Не объединяйте без необходимости, потому что это оскорбляет бога стиля: не это, print "\nReturning: " . $thiskey . "\n";, но print "\nReturning: $thiskey\n";, или если вам не нужен первый \n: say "Returning: $thiskey;" (только 5.10)
  • grep над 0 .. $#array; категорически хромает, просто по массиву grep: grep {} @{$foo[0]}, и с таким сложным кодом вы почти наверняка не захотите grep (хотя я не понимаю, что Вы делаете, чтобы быть честным.) Проверьте perldoc -q first - короче grep не останавливается до конца .

Наконец, не присваивайте массив скаляру: $thiskey = @result; является неявным $thiskey = scalar @result; (см. perldoc -q scalar) для получения дополнительной информации. Что вы, вероятно, хотите, это вернуть ссылку на массив. Как то так (что исключает $thiskey)

printf "\nReturning: %s\n", join ', ', @result;
@result ? \@result : 'NULL';
1 голос
/ 13 июня 2010

Если вы намереваетесь вернуть, найдено ли совпадение, этот код должен работать (неэффективно).Однако если вы намереваетесь вернуть ключ, этого не произойдет - скалярное значение @result (то, что вы получаете, когда говорите $thiskey = @result;) - это количество элементов в списке, а непервая запись.

$thiskey = @result;, вероятно, следует изменить на $thiskey = $result[0];, если вы хотите в основном функциональность, эквивалентную коду, на котором вы это основали.Обратите внимание, что он больше не будет учитывать несколько совпадений, если только вы не вернете @result полностью, что в любом случае имеет смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...