Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> попытка создать телефонный справочник, perl телефонный справочник 
:(
    Опции темы
tooncheg
Дата 20.5.2013, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Необходимо было изучить perl. Первоначально прочитал Рендала Шварца 5 издание и решил для тренировке создать тел. справочник. Создан файл текстовый БД вида:

Сидоров Самуил Виторганович::5533::113::Бухгалтерия
Петров Лев Игнатьевич::5322::114::Кадров
Иванов Иван Иванович::5322::119::56

Параметры предполагалось заводить через веб форму

Код

<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head><title>ФОРМА</title></head>
<body>
<h2>Заполните форму для поиска</h2>
<br>
<form method="get" action="http://site.ru/perl/form_temp.pl">
<pre>
Введите имя: <input type="text" name="name">
Введите фамилию: <input type="text" name="surname">
Введите отчество: <input type="text" name="patronymic">
Введите отдел: <input type="text" name="department">
Введите комнату: <input type="text" name="room">
Введите телефон: <input type="text" name="phone">
<input type=submit value=Поиск>
</form>
<body>
<html>



Задавал вопросы на схожем форуме, но в итоге все пришло к полной неразберихе. Вообщем если начать с чистого листа. Можете ли дать советы как может быть реализован поиск по БД. 
 
PM MAIL   Вверх
arto
Дата 20.5.2013, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



читать и сравнивать.
PM MAIL ICQ   Вверх
tooncheg
Дата 20.5.2013, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Цитата(arto @ 20.5.2013,  16:23)
читать и сравнивать.

В том и дело алгоритм сравнения меня и ввел в тупик.
Вот например:

Код

if (($phone =~ m/@{[param('phone')]}/) && ($room =~ m/@{[param('room')]}/)) {
  say "Фамилия: $name, Телефон: $phone Комната: $room <BR>" ;}
}


это кусок чернового варианта. что тут получается, если равны левые и правая часть, то условие выполнится, а если я в форме ввел только номер телефона, то условие не должно выполняться (на самом деле у меня происходит поиск, по одному параметру из формы, но выводится только первое совпадение из БД).
Именно так как вы предложили я и пытался решить задачу, но алгоритм сравнения оказался не так прост для меня.
PM MAIL   Вверх
arto
Дата 20.5.2013, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



а как надо? если не введен параметр, то как надо поступать?
PM MAIL ICQ   Вверх
vadiml
Дата 20.5.2013, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 27.7.2007

Репутация: 5
Всего: 7



Если задание отсюда https://www.reg.ru/company/jobs/testtask-prog
то там надо написать используя Catalyst, а не просто голый perl.
PM MAIL Jabber   Вверх
tooncheg
Дата 21.5.2013, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Цитата(arto @ 20.5.2013,  17:23)
а как надо? если не введен параметр, то как надо поступать?

Я читал строки так

Код

......
open my $fh, '<', 'phone.txt' or die "Error open phone.txt: $!\n";
while (<$fh>) {
  chomp;
  my ($name,$phone,$room, $otdel) = split /::/, $_;
.....


далее как тут советовали сравнивать. но вот тут как раз то и становится не ясно как это осуществить.

Код

if (($phone =~ m/@{[param('phone')]}/) && ($room =~ m/@{[param('room')]}/))

Операция поиска совпадения по шаблону в левой части - допустим true. Операция поиска совпадения по шаблону в правой части, параметр в форме не был введен - false. Условие же не выполнится. Или я недопонимаю что-то.
Я не знаю как надо поступать. Прочитать строки и сравнить, если это можно реализовать, то как это сделать.

PM MAIL   Вверх
arto
Дата 21.5.2013, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



прочитать поля в хеш (для удобства), затем

map { $_ => exists $hash{$_} && param($_) eq $hash{$_} } param()

получите хеш результатов сравнений существующих параметров (вместо eq можно взять регекс).
далее обрабатываете как вам удобно (предполагается, что param() -- функция из CGI* модулей).

А еще проще -- использовать какой-либо из валидаторов, типа Data::FormValidator
PM MAIL ICQ   Вверх
tooncheg
Дата 24.5.2013, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Цитата(arto @ 21.5.2013,  09:24)
прочитать поля в хеш (для удобства)

 У меня есть пару вопросов по поводу как занести данные в хэш .

я изменил текстовую БД 

1::Сидоров::Самуил::Виторганович::5533::113::Бухгалтерия
2::Петров::Лев::Игнатьевич::5322::114::Кадров
3::Иванов::Иван::Иванович::5322::119::56
 
потом читаю строки так

Код

while (<$fh>) {
  chomp;
  my ($number,$surname,$name,$patronymic,$phone,$room, $otdel) = split /::/, $_;
  %hoh = ($number => {
    'name' => $name,
    'surname' => $surname,
    'patronymic' => $patronymic,
     ........
         },
     
);
}
close $fh;


Но в результате хэш заполняется только последней строкой, т.е. в хэше содержится только последняя строка 3::Иванов::Иван::Иванович::5322::119::56
И вообще правильно ли я Вас понял, как надо прочитать поля в хэш?
PM MAIL   Вверх
alezzz
Дата 24.5.2013, 12:43 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


сплю...
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 17.8.2009

Репутация: 1
Всего: 14



Код

use strict;

my %hoh;
while (<DATA>){
    chomp;
    my ($number,$surname,$name,$patronymic,$phone,$room, $otdel) = split /::/, $_;
    $hoh{$number} =  {
        'name' => $name,
        'surname' => $surname,
        'patronymic' => $patronymic
    };
}

use Data::Dumper;
print Dumper %hoh;

__DATA__
1::Сидоров::Самуил::Виторганович::5533::113::Бухгалтерия
2::Петров::Лев::Игнатьевич::5322::114::Кадров
3::Иванов::Иван::Иванович::5322::119::56

PM MAIL   Вверх
tooncheg
Дата 28.5.2013, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Я извиняюсь. Просто потратил кучу времени, а справочник создать не получается даже после совета arto.

Код

#!/usr/bin/perl -w
#use strict;
use utf8::all;
use CGI::Carp qw(fatalsToBrowser);
use CGI qw/:param/;

 
print "Content-type: text/html; charset=utf-8 \n\n";
open my $fh, '<', 'phone.txt' or die "Error open phone.txt: $!\n";
while (<$fh>) {
  chomp;
  my ($number,$surname,$name,$patronymic,$phone,$room, $otdel) = split /::/, $_;
  $hoh{$number} = {
    'name' => $name,
    'surname' => $surname,
    'patronymic' => $patronymic,
    'phone' => $phone,
    'room' => $room,
    'otdel' => $otdel,
     }
}
%hoh_form = (
    'name' => param ('name'),
    'surname' => param ('surname'),
    'patronymic' => param ('patronymic'),
    'phone' => param ('phone'),
    'room' => param ('room'),
    'otdel' => param ('otdel'),
    );

?????????????????????????????????

close $fh;


Как реализовать сравнение введенного из формы и записанного в ХЭШ, и записанного в ХЭШ из текстового файла. Например, если в форме вводились данные номер телефона и фамилия с кем связан этот телефон, то выводились данные конкретного человека. 
Заранее спасибо.
PM MAIL   Вверх
arto
Дата 28.5.2013, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



map { ( $form{$_} || "" ) eq ( $file{$_} || "" ) } keys %form
PM MAIL ICQ   Вверх
ginnie
Дата 28.5.2013, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



tooncheg, напишите, как Вы представляете поиск, т.е. что вводится в поля и что должно быть выведено в качестве результата поиска (нужны примеры).


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
tooncheg
Дата 28.5.2013, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Цитата(ginnie @ 28.5.2013,  12:37)
tooncheg, напишите, как Вы представляете поиск, т.е. что вводится в поля и что должно быть выведено в качестве результата поиска (нужны примеры).

Самая простая форма. 6-ть полей куда вносятся данные для поиска Имя,Фамилия,Отчество,Отдел,Комната,Телефон. 

<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head><title>ФОРМА</title></head>
<body>
<h2>Заполните форму для поиска</h2>
<br>
<form method="get" action="http://site.ru/perl/form_temp.pl">
<pre>
Введите имя: <input type="text" name="name">
Введите фамилию: <input type="text" name="surname">
Введите отчество: <input type="text" name="patronymic">
Введите отдел: <input type="text" name="department">
Введите комнату: <input type="text" name="room">
Введите телефон: <input type="text" name="phone">
<input type=submit value=Поиск>
</form>
<body>
<html>

Данные передаются в скрипт form_temp.pl , модуль CGI помогает принять значения.
В поля вводятся либо остаются пустыми ИМЯ ФАМИЛИЯ ОТЧЕСТВО ОТДЕЛ КОМНАТА ТЕЛЕФОН. Например ввод ИМЕНИ ТЕЛЕФОНА ОТДЕЛА далее сравнение по текстовой БД и вывод ФАМИЛИИ ИМЕНИ ОТЧЕСТВА ТЕЛЕФОНА...я представляю это типа  выборки по введенным параметрам, но как сделать не знаю. 

PM MAIL   Вверх
ginnie
Дата 28.5.2013, 16:41 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



tooncheg, вот мой вариант без CGI и для текста в кодировке cp1251:

Код

#!/usr/bin/perl

use strict;
use warnings;

use locale;
use POSIX qw(:locale_h);

setlocale(LC_ALL, "ru_RU.CP1251");

my %directory;
while (<DATA>){
    chomp;
    my ($number,$surname,$name,$patronymic,$phone,$room, $otdel) = split /::/, $_;
    my $person =  {
        name => $name,
        surname => $surname,
        patronymic => $patronymic,
        phone => $phone,
        room => $room,
        otdel => $otdel,
    };
    $directory{number}{$number} = $person;
    while (my ($key, $value) = each %{$person}) {
        next if (!defined $value or $value eq '');
        push(@{$directory{$key}{lc $value}}, $number);
    }
}

my %query = (
#    surname => 'петров',
    phone => '5322',
);

my $round = 0;
my %results;
while (my ($key, $value) = each %query) {
    next if (!defined $value or $value eq '');
    $round++;
    my $numbers = $directory{$key}{lc $value} or next;
    for my $number (@{$numbers}) {
        $results{$number}++;
    }
}

while (my ($number, $counter) = each %results) {
    print join('::', @{$directory{number}{$number}}{qw{surname name patronymic phone room otdel}}), $/ if ($counter == $round);
}


__DATA__
1::Сидоров::Самуил::Виторганович::5533::113::Бухгалтерия
2::Петров::Лев::Игнатьевич::5322::114::Кадров
3::Иванов::Иван::Иванович::5322::119::56


Это сообщение отредактировал(а) ginnie - 28.5.2013, 17:19


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
tooncheg
Дата 30.5.2013, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



ginnie

Мне не очень понятны несколько строк

Код

$directory{number}{$number} = $person;


$person если его вывести на экран, то это будут ссылки на то где хранится в памяти хэш. Что в реальности происходит тут? Еще не понял для чего нужен  еще {number}.  

Код

push(@{$directory{$key}{lc $value}}, $number);


Что происходит тут?

Прошу отнестись снисходительно, т.к. я только учусь. Заранее спасибо.
PM MAIL   Вверх
ginnie
Дата 30.5.2013, 11:54 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



tooncheg, хэш позволяет нам получать определенные данные из набора по ключу. Это свойство мы используем для организации поиска. Для того, чтобы искать по номеру телефона, надо создать хэш, где ключем будет номер телефона, а значениями данные о людях. Т.к. один номер может быть у нескольких человек, значение в хэше будет массивом. Кроме номера телефона, поиск также может осуществляться по другим полям, поэтому будет несколько хэшей (равно количеству полей для поиска). Чтобы не дублировать в каждом хэше данные о людях, будем в значении хранить только идентификатор человека ($number) и добавим еще один хэш, где ключами будут идентификаторы, а значениями - данные о человеке ($directory{number}{$number} = $person;)
Все используемые хэши я оформил в едином хранилище, которое также представляет собой хэш %directory, в котором ключами являются названия полей.
Код

push(@{$directory{$key}{lc $value}}, $number);

Добавляем в данные для поля $key по ключу lc($value) идентификатор пользователя $number. lc используем для того, чтобы поиск был независимым от регистра.

Если еще есть какие-нибудь вопросы, не стесняйтесь задавать!


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
tooncheg
Дата 5.6.2013, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



ginnie

поясните пожалуйста строку из кода

$results{$number}++;

В бест пректисе встречалась подобная структура, но не смог разобраться. 
PM MAIL   Вверх
krypt3r
Дата 5.6.2013, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 359
Регистрация: 9.6.2009

Репутация: 2
Всего: 16



Инкремент элемента хэша %results с ключом $number
PM MAIL   Вверх
ginnie
Дата 5.6.2013, 11:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



tooncheg, алгоритм поиска такой:
допустим задано три поля для поиска, выполняем отдельно по каждому заданному значению поиск в соответствующем кэше. Результатом выборки из кэша будут идентификаторы людей (в выборке они не повторяются). На каждом из трех этапов увеличиваем на единицу значение в хэше результатов для найденных идентификаторов. После трех этапов поиска выбираем из данных хэша результатов идентификаторы, у которых значение равно количеству этапов.

Если алгоритм понятен, попробуйте дописать программу, выводя кроме полного совпадения, еще и результаты, которые были ближе всего к полному совпадению (т.е. совпали не все поля).  smile 

Это сообщение отредактировал(а) ginnie - 5.6.2013, 13:43


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
tooncheg
Дата 5.6.2013, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



Цитата(krypt3r @ 5.6.2013,  11:08)
Инкремент элемента хэша %results с ключом $number

Это понятно Что происходит? Если Значение хеша undef , т.е. 0 идет приращение на 1цу ?

Это сообщение отредактировал(а) tooncheg - 5.6.2013, 13:47
PM MAIL   Вверх
tooncheg
Дата 10.6.2013, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.5.2013

Репутация: нет
Всего: нет



ginnie,

Цитата(ginnie @ 5.6.2013,  11:42)
tooncheg
Если алгоритм понятен, попробуйте дописать программу, выводя кроме полного совпадения, еще и результаты, которые были ближе всего к полному совпадению (т.е. совпали не все поля).  smile

Код

#!/usr/bin/perl
use strict;
use warnings;
use locale;
use POSIX qw(:locale_h);
setlocale(LC_ALL, "ru_RU.CP1251");
use Data::Dumper;



my %directory;
open my $fh, '<', 'phone.txt' or die "Error open phone.txt: $!\n";

while (<$fh>){
    chomp;
    my ($number,$surname,$name,$patronymic,$phone,$room, $otdel) = split /::/, $_;
    my $person =  {
        name => $name,
        surname => $surname,
        patronymic => $patronymic,
        phone => $phone,
        room => $room,
        otdel => $otdel,
    };
    $directory{number}{$number} = $person;
       while (my ($key, $value) = each %{$person}) {
        next if (!defined $value or $value eq '');
        push(@{$directory{$key}{lc $value}}, $number);
        }
}
my %query = (
   surname => 'Иванов',
   phone => '5322',
   name => 'Иван',
   room => '112',
#   otdel => '7',
);
my $round = 0;
my %results;
while (my ($key, $value) = each %query) {
    next if (!defined $value or $value eq '');
    $round++;
    my $numbers = $directory{$key}{lc $value} or next;
    for my $number (@{$numbers}) {
         $results{$number}++;
         }
       }
 while (my ($number, $counter) = each %results) {
    print join('::', @{$directory{number}{$number}}{qw{surname name patronymic phone room otdel}}) $/ if ($counter ==$round) ;
}
my @counter = values %results;
my $max = $counter[0];
foreach (@counter) {
    if ($_ > $max)  {
        $max = $_
    }

foreach my $number (keys %results) {
    if ($max != $round and $results{$number}==$max) {
        print "Возможно : " . join('::', @{$directory{number}{$number}}{qw{surname name patronymic phone room otdel}}). "\n";
    }
}


вроде работает.
Появился вопрос. Каким образом происходит объединение в этой строке join('::', @{$directory{number}{$number}}{qw{surname name patronymic phone room otdel}}) не понимаю последовательность происходящего там.

Это сообщение отредактировал(а) tooncheg - 10.6.2013, 13:59
PM MAIL   Вверх
ginnie
Дата 10.6.2013, 15:11 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Цитата(tooncheg @  10.6.2013,  13:58 Найти цитируемый пост)
Появился вопрос. Каким образом происходит объединение в этой строке join('::', @{$directory{number}{$number}}{qw{surname name patronymic phone room otdel}}) не понимаю последовательность происходящего там.

Мне надо было вывести данные из справочника, сделал вывод полей через разделитель '::'. Т.к. данные хранятся в хэше, надо, чтобы значения вынимались в строго определенном порядке, используем вариант @hash{'field1', 'field2', 'field3'...'fieldN'}.
Последовательность такая:
  • строка 'surname name patronymic phone room otdel'  преобразуется оператором qw{} в список строковых значений ('surname', 'name' и т.д),
  • из хэша данных о человеке $directory{number}{$number} выбирается список значений полей,
  • список значений объединяется в одну строку с использованием разделителя '::'.


Это сообщение отредактировал(а) ginnie - 10.6.2013, 15:12


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1275 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.