Форум программистов, компьютерный форум, киберфорум
Наши страницы
Perl
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
1

Сортировка текста по алфавиту

05.10.2016, 11:32. Просмотров 1681. Ответов 20
Метки нет (Все метки)

Добрый день. В Перл новичок, а сам язык вызывает большой интерес. Книги читаем, практики пока мало. Читал главу sort , но так и не разобрался. В общем сам вопрос, как реализовать сортировку по алфавиту в текстовом файле в котором указаны Ф.И.О полностью. Можно было бы примером показать?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.10.2016, 11:32
Ответы с готовыми решениями:

Сортировка текста по алфавиту(А-Я) и (Я-А)
Помогите, пожалуйста, с кодом сортировки, я не как не могу найти нормальный код сортировки текста...

Сортировка текста по алфавиту
Разработать программу который произвольный текст будет сортировать по алфавиту. Чтение происходит...

Сортировка текста по алфавиту
Нужна помощь. нужно написать консольную программу, которая бы сортировала текст из заданного ей...

Сортировка текста по алфавиту
Cоздать програму, какая имеет некоторый текст и выводит его в алфавитном порядке, начальную строку...

Сортировка текста из файла по алфавиту
Программа открывает файл и сортирует слова текста за алфавитом. Работает в Code::Blocks но не...

20
CurrentUser
25 / 25 / 14
Регистрация: 29.09.2014
Сообщений: 156
05.10.2016, 15:14 2
Лучший ответ Сообщение было отмечено aleks_maked как решение

Решение

В перле есть встроенная функция sort которая сортирует в ASCII алфавитном порядке она вам подайдет.

Вот пример
sort.pl
Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!perl
use strict;
use warnings;
# Открываем файл с именем которое передается как аргумент 
#если его нет открываем файл fio.txt по пути D:\perl\fio.txt 
my $dir = 'D:\perl';
chdir $dir or die "Error open chdir to $dir  $!";
my $file_name = shift || 'fio.txt';
open FIO, "$file_name" or die "Error open file $file_name $!";
#Построчно считываем содержимое файла в массив @fio
my @fio;
while (<FIO>) {
chomp;
unshift(@fio, $_);
}
close FIO;
#Сортируем по убыванию и печатаем результат 
for (sort @fio) {
print "$_\n";
}
Вот данные в файле fio.txt (не сортированные )
Кликните здесь для просмотра всего текста
AA AC AC
AA AB AC
AA AA AC
AA AA AB
AA AA AA
BB AA AA


после запуска программы данные стали сортированы по алфавиту
C:\Users\Root>D:\perl\sort.pl
AA AA AA
AA AA AB
AA AA AC
AA AB AC
AA AC AC
BB AA AA

PS Еще в перле есть расширенная сортировка , советую с ней подружиться =)
1
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
05.10.2016, 16:52  [ТС] 3
Спасибо большое, дальше сам буду разбираться
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
06.10.2016, 04:11 4
Лучший ответ Сообщение было отмечено aleks_maked как решение

Решение

по-возрастанию; лексикографически
Perl
1
2
3
4
5
print
for
sort
grep /\w+/,
< ZKL A c d b : 56 : 100 7 U + z  - y  = x  >
по-убыванию; лексикографически
Perl
1
2
3
4
5
print
for
sort { $b cmp $a }
grep /\w+/,
< ZKL A c d b : 56 : 100 7 U + z  - y  = x  >
только числа; по убыванию; натурально
Perl
1
2
3
4
5
print
for
sort { $b <=> $a }
grep /\d+/,
< ZKL A c d b : 56 : 100 7 U + z  - y  = x  >
1
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
06.10.2016, 12:37  [ТС] 5
Спасибо за ответы. Не много подправил код
Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/perl -w 
 
use strict;
use utf8;
use open qw(:std :utf8);
 
# Открываем файл с именем которое передается как аргумент  
      my $dir = '.';
      my $file_name = shift || 'names.txt';
      open src, "$file_name" or die "Error open file $file_name $!";
  #Построчно считываем содержимое файла в массив @fio
      my @fio;
      while (my $s = <src>) {
        chomp $s;
        push @fio, $s;
        }
  close src;
  #Сортируем по убыванию без учета регистра
  
    my @sorted = sort  { uc($a) cmp uc($b) } @fio; 
 
  foreach my $s (@sorted) {
    print "$s\n";
  }
Тепрерь думаю как можно сделать, чтобы тот файл который мы открываем и считываем обновился с новыми данными (т.е. записался сортированным списком), возможно можно сначала открыть файл для чтения, прочитать, отсортировать, открыть файл для записи (все удалится) и записать.
А второе как можно отсортированные данные записать в отдельный файл, есть вроде команда
open (FILE, ">>name.txt");
print FILE $name;
close (FILE);
но что то у меня не получается
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
06.10.2016, 13:13 6
Лучший ответ Сообщение было отмечено aleks_maked как решение

Решение

всё, что у тебя написано в 20 строках,
можно реализовать одной, включая создание нового отсортированного файла.

Perl
1
2
3
4
5
6
7
8
9
10
use strict;
use utf8;
use open qw(:std :utf8);
 
my $filename = shift || 'names.txt';
 
open UNSORTED, $filename or die $!;
open SORTED, '>', "sorted_$filename" or die $!;
 
print SORTED for sort { uc($a) cmp uc($b) } <UNSORTED>;
1
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
06.10.2016, 13:57  [ТС] 7
а зачем в 5 строке вы пишите my $filename = shift || 'names.txt';

Добавлено через 6 минут
разобрался, спасибо )))
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
06.10.2016, 14:29 8
Цитата Сообщение от aleks_maked Посмотреть сообщение
а зачем в 5 строке вы пишите my $filename = shift || 'names.txt';
просто скопировал твою 9-ю строчку
или ты что-то другое имел в виду ?

Добавлено через 29 минут
a может тебя Perl6 заинтересует ?

эквивалентный код для Perl6:
Perl
1
2
3
4
5
sub MAIN( $filename = "names.txt" ) {
    spurt "sorted_$filename",
          $filename.IO.lines.sort(*.uc).join("\n");
 
}
2
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
10.10.2016, 12:25  [ТС] 9
Всем спасибо за ответы!!! Очень помогло. Назрел новый вопрос, как реализовать сортировку по номеру телефонов вида 123-45-67

Добавлено через 38 минут
если написать так
Perl
1
my @sorted = (sort { $b <=> $a }  @fio);
, то консоль ругается таким текстом Argument "\x{421}\x{443}..." isn't numeric in sort at sort2 line 21., но сортировка происходит
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
10.10.2016, 13:47 10
Цитата Сообщение от aleks_maked Посмотреть сообщение
консоль ругается таким текстом Argument "\x{421}\x{443}..." isn't numeric in sort at sort2 line 21.,
если ты не будешь подсовывать функции сортировки буквы вместо цифр, то и ругаться никто не будет,
зуб даю.
0
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
10.10.2016, 15:08  [ТС] 11
А что если подключить реулярное выражение, которое будет заносить в шех массив с ключом-номер телефона. а значение будет - ФИО
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
10.10.2016, 18:22 12
обыЧно наоборот, в жизни, то есть, в нашей;
one-to-many - на одну фамилию много телефонов,
но, безусловно, выбор за тобой.
1
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
11.10.2016, 11:13  [ТС] 13
я пока просто тренируюсь, могли бы подсказать с кодом?
Perl
1
2
3
4
5
6
7
# Проверяем, похожа ли строка на ключ=значение
    if ($s =~ /^([а-я]+)\s([а-я]+)\s([а-я])\s+=\d+/-\d+/-\d+/) {
      print"$s\n"
      # Похожа
      TelephoneNumber($1, $2);
      next;
    }
здесь я проверяю строку на похожесть, если да, то запускается процедура
Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sub TelephoneNumber 
{
    my $key = shift;
    my $value = shift;
    # Разобрать строку на ключ-значение
    my $name;
    my $number;
    if ($s =~ /^([а-я]+)\s([а-я]+)\s([а-я]+)\s+\d+/-\d+/-\d+/) {
      $name = $1;
      $number = $2;
    } else {
      die "Ошибка разбора строки\n";
    }
    # Кусочки занести в хеш
    $telephone{$1} = \{number => $1, name => $2};
}
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
11.10.2016, 11:42 14
Цитата Сообщение от aleks_maked Посмотреть сообщение
я пока просто тренируюсь, могли бы подсказать с кодом?
тренируйся, но код по-прежнему ужасен ))

Добавлено через 3 минуты
Перл - это не Си,
на нём можно всё делать гораздо компактнее,
это улучшает стиль, уменьшает возможность ошибок
и, что самое главное, приносит чувство удовлетворения.

Добавлено через 4 минуты
выделять разбор строки в подпрограмме нет надобности,
а особенно умирать в ней из-за вздорной причины несовпадения
шаблона рег. выражения со строкой.

Добавлено через 10 минут
Как захваченные строки в этом выражении
Perl
1
$s =~ /^([а-я]+)\s([а-я]+)\s([а-я]+)\s+\d+/-\d+/-\d+/
соотносятся с этим
Perl
1
$telephone{$1} = \{number => $1, name => $2};
предложением ?
1
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
11.10.2016, 11:50  [ТС] 15
Вот и пришел сюда за советом ))) Хочется освоить этот язык. Могли бы показать на коде , как будет лучше выглядеть разбиение строки по регулярному выражению и занесение его в хеш
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
11.10.2016, 13:15 16
Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use utf8;
 
my %АБОНЕНТЫ;
 
while(<DATA>) {
 
  /
  ^
  (?<ФАМИЛИЯ> [\w `-]+)
  \s+  
  (?<ИМЯ> [\w ]+)
  \s+
  (?<ОТЧЕСТВО> [\w]+)
  \s+
  (?<ТЕЛЕФОН> [+ \d () -]+)
  \s*
 
  /x and push @{ $АБОНЕНТЫ{ join ';', $+{ФАМИЛИЯ}, $+{ИМЯ}, $+{ОТЧЕСТВО} } }, $+{ТЕЛЕФОН}
 
}
 
for ( sort keys %АБОНЕНТЫ ) {
 
    my ($Ф,$И,$О) = split ';';
  
    print "$Ф $И $О : ", join(';', @{$АБОНЕНТЫ{$_}}), "\n";
}
 
 
__DATA__
Бестужев-Рюмин Аристарх Бенедиктович +7(910)123-34-45
Гей-Люссак Корней Степаныч 499-11-19
д`Артаньян Николай Николаевич 123-45-90
д`Артаньян Николай Николаевич 916-890-42-23
1
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
11.10.2016, 13:42  [ТС] 17
А можно коменты написать? что делается.
как я понял в 3-й строке my %АБОНЕНТЫ; - это создается хеш.
с 7 по 16 идет заполнение хеша, 18 строку не пойму. в с 22 по 24 идет разделение сплитом, в конце вывод. правильно?
Цикл data не пойму ((
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
11.10.2016, 13:48 18
с 7 по 16-ю идёт разбор с захватом в именованные ссылки,
а в 18-ой - заполнение хэша по результату захвата.

ключом хэша будут являться Ф;И;О ( разделённые ; ) ( ну вот так я придумал ),
а значением - список номеров.
0
aleks_maked
0 / 0 / 0
Регистрация: 05.10.2016
Сообщений: 11
11.10.2016, 15:54  [ТС] 19
И еще момент, мы ведь должны сортировать по номеру телефона

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

Добавлено через 16 секунд
И все же как будет выглядеть правильный код, если использовать регулярные выражения, занести их в хеш и уже дальше их вывести в отдельный файл. Можно показать хотя бы как правильно написать цикл по регулярному выражению с заносом в хеш? саму регулярку представляю как составить, а вот поместить это в цикл и занести в хеш... проблема
0
volodin661
2572 / 1118 / 194
Регистрация: 10.12.2013
Сообщений: 3,772
12.10.2016, 06:34 20
я не знаю, что ты хочешь со всем этим делать,
но если тебя интересует только телефон в качестве ключа хэша,
составь именно такой хэш, данные уже благополучно разобраны.

Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
while(<DATA>) {
 
  /
  ^
  (?<ФАМИЛИЯ> [\w `-]+)
  \s+  
  (?<ИМЯ> [\w ]+)
  \s+
  (?<ОТЧЕСТВО> [\w]+)
  \s+
  (?<ТЕЛЕФОН> [+ \d () -]+)
  \s*
 
  /x and $АБОНЕНТЫ{ $+{ТЕЛЕФОН} } =
          { 
              'ФАМИЛИЯ'  =>  $+{ФАМИЛИЯ},
                   'ИМЯ'  =>  $+{ИМЯ} ,
              'ОТЧЕСТВО'  =>  $+{ОТЧЕСТВО} 
          };
}
Добавлено через 1 час 22 минуты
вот как-то так вот:

Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use utf8;
use strict;
 
my %АБОНЕНТЫ;
while(<DATA>) {
  
  /
    ^
    (?<ФАМИЛИЯ> [\p{Block: Cyrillic} `-]+)
    \s+  
    (?<ИМЯ>      [\p{Block: Cyrillic}   ]+)
    \s+
    (?<ОТЧЕСТВО> [\p{Block: Cyrillic}   ]+)
    \s+
    (?<ТЕЛЕФОН>  [+ \d ()              -]+)
    \s*
  /x and $АБОНЕНТЫ{ $+{ТЕЛЕФОН} } =
         {
               ФАМИЛИЯ =>  $+{ФАМИЛИЯ},
                   ИМЯ  =>  $+{ИМЯ} ,
              ОТЧЕСТВО  =>  $+{ОТЧЕСТВО} 
         };
}
 
for my $телефон ( sort keys %АБОНЕНТЫ ) {
    printf "у меня зазвонил $телефон:\n";
    printf "- Kто говорит? \n";
    printf "- %s %s %s \n", $АБОНЕНТЫ {$телефон} {ФАМИЛИЯ},
                            $АБОНЕНТЫ {$телефон} {ИМЯ},
                            $АБОНЕНТЫ {$телефон} {ОТЧЕСТВО};
}
 
 
 
 
 
__DATA__
Д`Артаньян Николай Николаевич 8 929 123-45-90
Д`Артаньян Николай Николаевич 916-890-42-23
Бестужев-Рюмин Аристарх Бенедиктович +7(910)123-34-45
Гей-Люссак Корней Степаныч 499-11-19
Лошадёв Овсей Ильич 999 000 666
Добавлено через 10 часов 46 минут
использованные Perl-идиомы:

1) Цикл while с т.н алмазом <>
Perl
1
2
3
while ( <DATA> ) {
    ...
}
это построчное чтение из файла,
внутри угловых скобок находится файл-манипулятор,
в данном случае это предопределённый манипулятор DATA,
то есть, чтение происходит из нашего же скрипт-файла из области,
помеченной как __DATA__.
Каждая прочитанная строка попадает в скалярную переменную-по-умолчанию $_.
ещё раз: оператор while определяет скалярный контекст чтения из файла с помощью оператора угловых скобок <>(алмаз)
если бы вместо while был бы оператор for, то мы бы получили списковый контекст чтения из файла.

2) Внутри тела цикла находится Regexp-оператор, заданный двумя слэшами ( / / ) и оформленный вертикально( в столбик )
для удобства чтения его внутренних конструкций.
Perl
1
2
3
4
5
6
/
...
...
...
...
/x;
завершается он модификатором x,
который позволяет расширенное толкование regexp-закорючек (все литеральные пробелы игнорируются )
Perl
1
2
3
4
5
6
7
8
9
10
11
/
    ^                                         # начало строки
    (?<ФАМИЛИЯ> [\p{Block: Cyrillic} `-]+)  # кириллические символы, а также символ тире(-) и (`) захватятся во внутренний именованный хэш, представленный глобальной переменной %+     
    \s+  
    (?<ИМЯ>      [\p{Block: Cyrillic}   ]+)  # кириллические символы захватятся во внутренний именованный хэш, представленный глобальной переменной %+   
    \s+
    (?<ОТЧЕСТВО> [\p{Block: Cyrillic}   ]+)
    \s+
    (?<ТЕЛЕФОН>  [+ \d ()              -]+)  # кириллические символы, а также символ тире(-) и цифры  захватятся во внутренний именованный хэш, представленный глобальной переменной %+   
    \s*
/x;
конструкция \p{Block: Cyrillic} - это т.н unicode-properties, можно было бы записать покороче \p{Cyrillic}
Если нас интересуют не только русские, но и прочие буквы, можно было бы записать так: \p{L}
( за деталями добро пожаловать в документацию http://perldoc.perl.org/perlunicode.html )
конструкция (?<имя> шаблон) - позволяет проименовать шаблон для удобства последующего к нему обращения через переменную %+

3) далее
Perl
1
2
3
4
5
6
... and $АБОНЕНТЫ{ $+{ТЕЛЕФОН} } =
         {
               ФАМИЛИЯ =>  $+{ФАМИЛИЯ},
                   ИМЯ  =>  $+{ИМЯ} ,
              ОТЧЕСТВО  =>  $+{ОТЧЕСТВО} 
         };
логический оператор and говорит нам о том, что заполнение хэша %АБОНЕНТЫ произойдёт
только в случае успешного завершения regexp-выражения, то есть, если все шаблоны внутри него
успешно совпадут.
Итак, имеется наш придуманный хэш %АБОНЕНТЫ след. вида
Perl
1
2
3
4
5
%АБОНЕНТЫ ( 
                   '8 929 123-45-90' =>  { 'ФАМИЛИЯ' => 'Д`Артаньян', 'ИМЯ' => 'Николай', 'ОТЧЕСТВО' => 'Николаевич'}
                   '8 929 123-45-90' =>  { 'ФАМИЛИЯ' => ..., 'ИМЯ' => ..., 'ОТЧЕСТВО' => ...} 
                   '499-11-19'       =>  { 'ФАМИЛИЯ' => ..., 'ИМЯ' => ..., 'ОТЧЕСТВО' => ...}
);
$+{ТЕЛЕФОН} - обращение к глобальному хэшу %+, чтобы извлечь именованный шаблон <ТЕЛЕФОН>
$+{ФАМИЛИЯ} - обращение к глобальному хэшу %+, чтобы извлечь именованный шаблон <ФАМИЛИЯ>
$+{ИМЯ} - обращение к глобальному хэшу %+, чтобы извлечь именованный шаблон <ИМЯ>
$+{ОТЧЕСТВО} - обращение к глобальному хэшу %+, чтобы извлечь именованный шаблон <ОТЧЕСТВО>

4) Обращение к заполненным полям хэша %АБОНЕНТЫ производится вот так:
Perl
1
$АБОНЕНТЫ{ 'номер-телефона' }->{'ФАМИЛИЯ'}
но оператор стрелка -> можно безболезненно опустить, компилятор - не дурак, разберётся:
Perl
1
$АБОНЕНТЫ{ 'номер-телефона' }{'ФАМИЛИЯ'}
можно также вставить пробел между операторами фигурные скобки и между именем хэша и фиг. скобками:
Perl
1
$АБОНЕНТЫ {'номер-телефона'} {'ФАМИЛИЯ'}
Добавлено через 13 минут
Цитата Сообщение от volodin661 Посмотреть сообщение
$+{ТЕЛЕФОН} - обращение к глобальному хэшу %+, чтобы извлечь именованный шаблон <ТЕЛЕФОН>
поправка, следует читать так:
$+{ТЕЛЕФОН} - обращение к глобальному хэшу %+, чтобы извлечь значение ,
захваченное regexp с помощью именованного шаблона <ТЕЛЕФОН>

Добавлено через 20 минут
отвечая на вопрос:
Цитата Сообщение от aleks_maked Посмотреть сообщение
как занести их в хеш и уже дальше их вывести в отдельный файл?
надо открыть файл на запись
Perl
1
open LOG, '>', 'myfile.log' or die $!;
и подставить этот манипулятор первым аргументом оператору printf в строках 26-28
Perl
1
printf LOG "у меня зазвонил $телефон:\n";
либо выбрать LOG манипулятором по умолчанию с помощью функции select()
и тогда можно оставить, как было
Perl
1
2
3
4
5
6
7
8
9
open LOG, '>', 'myfile.log' or die $!;
select LOG;
for my $телефон ( sort keys %АБОНЕНТЫ ) {
    printf "у меня зазвонил $телефон:\n";
    printf "- Kто говорит? \n";
    printf "- %s %s %s \n", $АБОНЕНТЫ {$телефон} {ФАМИЛИЯ},
                            $АБОНЕНТЫ {$телефон} {ИМЯ},
                            $АБОНЕНТЫ {$телефон} {ОТЧЕСТВО};
}
1
12.10.2016, 06:34
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.10.2016, 06:34

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Сортировка блоков текста по алфавиту.
Есть текст вида Заголовок1 текст1 Заголовок2 текст2 Заголовок3 текст3

Сортировка текста по алфавиту (ООП)
Отсортировать в объектно ориентированном программировании. Сделать так, чтобы сначала сортировались...

Сортировка текста в строке по алфавиту (латынь)
Необходимо написать программу на языке C++, а именно: Реализовать программу, демонстрирующую...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.