Nano Hash - криптовалюты, майнинг, программирование

Проблемы с порядком вывода после возврата нескольких значений через подпрограмму в Perl

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

Id: Animal1
Loc: Area1
Similarity: 15/20

Id: Animal2
Loc: Area2
Similarity: 19/20

Id: Animal3
Loc: Area3
Similarity: 13/20

Поскольку у меня есть несколько файлов, которые я хочу запустить в одном скрипте, я хотел прочитать их в виде подпрограммы. Однако моя команда полностью портит порядок вывода. Любые идеи о том, какая ошибка в моем коде может быть причиной этого?

Вот код, который работает, когда он не в формате подпрограммы, начиная после того, как я открываю файл:

open($fh, "<", $animal1) || die "Could not open file $animal1/n $!";

while (<$fh>) {
    chomp;
    if($_ =~ /Id:\s+(\S+)/){
        $id= $1;

    }
    if($_ =~ /Loc:\s+(\S+)/){
        $loc{$id}= $1;
    }
    if($_ =~ /Similarity:\s+(\S+)/){
        $simil{$id}= $1;
    }
}

foreach $id(keys %loc){
    print "The $animal is found in $loc{$animal} and is $simil{$animal} similar\n";
}
close $fh;

Рассматриваемый код:

open($fh, "<", $animal1) || die "Could not open file $animal1/n $!\n";

while (<$fh>) {
    chomp;
    ($animal, $loc{$animal}, $simil{$animal})= parse_key_file($_);
}

foreach $animal(keys %loc){
    print "The $animal is found in $loc{$animal} and is $simil{$animal} similar\n";
}

sub parse_key_file {
    if($_ =~ /Id:\s+(\S+)/){
        $id= $1;
        next;
    }
    if($_ =~ /Loc:\s+(\S+)/){
        $loc{$id}= $1;
        next;
    }
    if($_ =~ /Similarity:\s+(\S+)/){
        $simil{$id}= $1;
        next;
    }
    return ($id, $loc{$id}, $simil{$id});
}

Благодарю вас ! А.


Ответы:


1

Однако моя команда полностью искажает порядок вывода. Любые идеи о том, какая ошибка в моем коде может быть причиной этого?

Это не ошибка в вашем коде (хотя прислушайтесь к предложениям Дэйва Кросса). Это ошибка в вашем понимании типа хэш-переменной Perl и функции keys. Тип хэша неупорядоченный, и нет гарантии, в каком порядке хэш-ключи будут возвращены вам в функции keys. Чтобы вернуть их в определенном порядке (скажем, в том порядке, в котором они встречаются во входном файле), вам придется следить за этим самостоятельно.

my (%seen,@order);
sub parse_key_file {
    if($_ =~ /Id:\s+(\S+)/){
        $id= $1;
        if (!$seen{$id}++) {
            push @order, $id;
        }
        next;
    }
    ...
}

foreach $animal (@order) {
    print "The $animal is found in $loc{$animal} and is $simil{$animal} similar\n";
}

Существует также модуль под названием Tie::IxHash, который предоставляет хэш-переменные, которые сохраняют порядок ввода своих ключей. , когда вы будете готовы использовать модули Perl.

26.09.2019

2

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

Давайте начнем с написания подпрограммы, которая берет один из ваших «абзацев» данных об одном животном и превращает его в хэш.

sub parse_animal {
  my ($input) = @_;

  my %animal;

  for (split /\n/, $input) {
    next unless /\S/;

    if (/Id:\s+(\S+)/) {
      $animal{id} = $1;
      next;
    }
    if (/Loc:\s+(\S+)/) {
      $animal{loc} = $1;
      next;
    }
    if (/Similarity:\s+(\S+)/) {
      $animal{simil} = $1;
      next;
    }
    warn "Unknown data line: $_";
  }

  return \%animal;
}

Это очень похоже на ваш код, за исключением того, что он использует только данные, переданные в качестве параметров, и создает и возвращает хэш информации.

Мы можем проверить это, вставив такую ​​программу:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';
use Data::Dumper;

my $animal1 = 'animals.dat';

open(my $fh, "<", $animal1) || die "Could not open file $animal1: $!\n";

local $/ = '';

while (<$fh>) {
  my $animal = parse_animal($_);
  say Dumper $animal;
}

sub parse_animal {
  ...
}

Здесь мы используем Data::Dumper, чтобы посмотреть, что вы получите в результате подпрограммы. Я получаю это:

$VAR1 = {
          'loc' => 'Area1',
          'id' => 'Animal1',
          'simil' => '15/20'
        };

$VAR1 = {
          'simil' => '19/20',
          'id' => 'Animal2',
          'loc' => 'Area2'
        };

$VAR1 = {
          'simil' => '13/20',
          'id' => 'Animal3',
          'loc' => 'Area3'
        };

Итак, мы видим, что а) мы правильно анализируем данные и б) данные для каждого животного остаются вместе в одном хэше.

Так что же на самом деле делать с данными, которые мы получаем? Ну, есть (по крайней мере!) пара вариантов. И что выбрать, зависит от того, что вы хотите, чтобы ваша программа делала.

Если вы хотите обрабатывать информацию о животных в том порядке, в котором они появляются во входном файле, то имеет смысл хранить их в массиве.

my @animals;

while (<$fh>) {
  push @animals, parse_animal($_);
}

for (@animals) {
  say "The $_->{id} is found in $_->{loc} and is $_->{simil} similar";
}

Другим вариантом может быть сохранение их в хеше (возможно, с ключом по идентификатору):

my %animals;

while (<$fh>) {
  my $animal = parse_animal($_);
  $animals{$animal->{id}} = $animal;
}

say Dumper \%animals;

Но, надеюсь, это дало вам достаточно информации, чтобы избавиться от застревания.

26.09.2019
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..