使用函数从对象或散列中检索值

时间:2014-07-01 20:34:13

标签: perl

如何分解值并单独返回,以便我可以单独访问它们?

我有一个带有数据库的论坛系统,可以跟踪线程中的所有帖子。我有一个名为notice_value的小组:

sub notice_value {
    my ($self,$prefid,$value,$others_post,$clients_post,$assigned_tasks) = @_;

    $self->{PREFS}->{$prefid} = { VALUE => $value,
                                  OTHERS_POST => $others_post,
                                  CLIENTS_POST => $clients_post,
                                  ASSIGNED_TASKS => $assigned_tasks };
    return $self->{PREFS}->{$prefid};
}

EDIT-原始notice_value

sub notice_value {
    my $self = shift;
    my $prefid = shift;
    $self->{PREFS}->{$prefid} = shift if(@_);
    return $self->{PREFS}->{$prefid};
} 

-------------------------------------------- -----------------

检索用户的首选项,其中一个是标记类型VALUE。当我调用标记类型时,我使用$self->markup来调用 - sub markup_type这是Taskman::Post中的方法:

sub markup_type {
    my $self = shift;
    $self->{MARKUP_TYPE} = shift if(@_);
    $self->{MARKUP_TYPE};
}

我的问题是我只想从notice_value中检索VALUE,而是返回整个事情 - 当我转储$self时,我得到了:

$VAR1 = bless( {
                 'POST_TYPE_ID' => 1,
                 'MINUTES' => '0',
                 'DEADLINE' => '2014-05-19 18:04:00',
                 'ESTIMATE' => 300,
                 'COMMENT' => 'sd',
                 'POSTER' => 1286,
                 'STATE_ID' => 14,
                 'CONTRACTID' => 546,
                 'PRIORITY' => '3',
                 'MARKUP_TYPE' => {
                                    'VALUE' => 1,
                                    'OTHERS_POST' => 1,
                                    'CLIENTS_POST' => 1,
                                    'ASSIGNED_TASKS' => 1
                                  },
                 'TID' => 23133,
                 'OWNER' => '1286'
               }, 'Taskman::Post' );

我希望能够分别访问其他值(OTHERS_POSTCLIENTS_POSTASSIGNED_TASKS)以及其他功能。

我是Perl的新手,对于如何分解notice_value sub感到有些困惑,这样我就能更有效,更正确地从中检索出我想要的内容。如果你能展示一个很好的例子。

修改

这是调用notice_value

的子
sub __populate {
    my $self = shift;

    my $sth = $self->{dbh}->prepare("select prefid, value, others_post, clients_post, assigned_tasks from user_preferences where userid=?");
    $sth->execute($self->userid);
    while(my $href = $sth->fetchrow_hashref()) {

        $self->notice_value($href->{PREFID}, $href->{VALUE}, $href->{OTHERS_POST}, $href->{CLIENTS_POST}, $href->{ASSIGNED_TASKS});
    }
    $sth->finish();
}

原始__populate只有:

$self->notice_value($href->{PREFID}, $href->{VALUE});

3 个答案:

答案 0 :(得分:1)

TL; DR 对广泛问题的广泛猜测/结论:修复notice_value的返回值或修复该值在其他函数中使用的方式。

这个问题非常笼统,并没有提供太多示例代码:事实上,由于问题的范围很广,它几乎无法按照定义发布示例代码。将问题发布为一般调试策略可能会更好(尽管我不确定这些查询是如何被接受的那样)或者 - 一旦你缩小了你的问题 - 发布关于修复技术的更具体的问题出了什么问题。

许多事情都可能出错:您的notice_value子例程的返回值是不是应该像return $self->{PREFS}->{$prefid}->{VALUE}; ie if - 从名称猜测 - 子程序应该“注意”散列/对象的MARKUP密钥匿名散列密钥的“值”VALUE它是一个“getter”方法/函数除了访问值之外什么也不做。它获取这些值的方式(解除引用,访问数据库等)留作该函数的实现细节。如果取消引用一个充满首选项的数据结构不起作用,并且当您更改访问您的首选项的功能时您的预期行为会发生变化,那么您就可以在正确的轨道上集中注意力了:)

如果我按如下方式创建一个函数并将它传递给一个数组(省略你传入的对象,那么我就省略了$self):

sub notice_value{ 
        my ($prefid,$value,$others_post,$clients_post,$assigned_tasks) = @_; 
        $_->{PREFS}->{$prefid} = { VALUE => $value,
                                   OTHERS_POST => $others_post,
                                   CLIENTS_POST => $clients_post, 
                                   ASSIGNED_TASKS => $assigned_tasks };

        return $_->{PREFS}->{$prefid}; 
}

现在有一些偏好和数据gunk:

my @pref_and_data_goo = qw( 21323 42 213 214 2 );

现在让我们看一下该函数的作用,它创建一个PREFS哈希键,并为其提供一个匿名哈希作为其值:

notice_value(@pref_and_data_goo)
    $HASH1 = {
              ASSIGNED_TASKS => 2,
              CLIENTS_POST   => 214,
              OTHERS_POST    => 213,
              VALUE          => 42
              };

VALUE密钥的值(我很容易被这里的命名方案弄糊涂)或PREFS密钥的匿名哈希中的其他密钥怎么样:

 notice_value(@pre_and_data_goo)->{VALUE}
 42 
 notice_value(@pre_and_data_goo)->{ASSIGNED_TASKS}
 214

如果你想要结束notice_value,那么它只返回VALUE键的值,你需要告诉该函数的代码如何获得该嵌套的匿名散列键。


现在将哈希/对象传递给您的其他函数markup_type并快速剪切并粘贴到re.pl(因此奇数标记例如 re.pl$>):

         re.pl$ my $whacky_hash = {
              > 'POST_TYPE_ID' => 1,
              > 'MINUTES' => '0',
              > 'DEADLINE' => '2014-05-19 18:04:00',
              > 'ESTIMATE' => 300,
              > 'COMMENT' => 'sd',
              > 'POSTER' => 1286,
              > 'STATE_ID' => 14,
              > 'CONTRACTID' => 546,
              > 'PRIORITY' => '3',
              > 'MARKUP_TYPE' => {
              >                   'VALUE' => 42,
              >                   'OTHERS_POST' => 1,
              >                   'CLIENTS_POST' => 1,
              >                   'ASSIGNED_TASKS' => 1
              >                 },
              > 'TID' => 23133,
              > 'OWNER' => '1286'
              > }
         re.pl$ sub markup_type {my $self = shift; 
              > $self->{MARKUP_TYPE} = shift if(@_); 
              > $self->{MARKUP_TYPE}; }
         re.pl$ markup_type($whacky_hash)
         $HASH1 = {
                    ASSIGNED_TASKS => 1,
                    CLIENTS_POST   => 1,
                    OTHERS_POST    => 1,
                    VALUE          => 1
                    };            
         re.pl$ sub markup_type2 {my $self = shift ; 
              > $self->{MARKUP_TYPE}->{VALUE}; }            
         re.pl$ markup_type2($whacky_hash)
         42

你确定类似的改变不起作用吗?如果您将markup_type功能更改为:

sub markup_type {
     my $self = shift ; 
     $self->{MARKUP_TYPE}->{VALUE}; 
}

你应该得到你想从该函数返回的值。如果这打破了其他代码,则跟踪它的使用位置,并尝试找到最适合尝试更改的地方。不幸的是,我们无法帮助您直接帮助您。

您的notice_value函数需要一长串赋值作为参数:

my ($self,$prefid,$value,$others_post,$clients_post,$assigned_tasks) = @_;

我倾向于不喜欢具有长列表分配的函数,因为很难将值追溯到它们来自的位置。 $value应该是哈希引用还是对markup_type或其他内容的返回值的代码引用?这可能只是我很容易混淆,因为许多人更喜欢列表分配方式。尽管如此,如果它应该做的只是notice_value,那么这个函数需要很多参数?您的尝试如果您检查notice_value如何获取并使用其参数,您将能够更轻松地发现错误的来源。您的 EDIT 添加仍然让我感到疑惑:为什么使用$href->{VALUE}而不是$href->{MARKUP_TYPE}->{VALUE}

答案 1 :(得分:1)

我注意到您的转储在转储结束时有Taskman::Post。这意味着这是一个Taskman::Post 对象,因此应该有方法,它将提取它包含的各种数据。可能有标记方法将提取此对象中的信息。

问题是这个对象来自何处。这是你写的吗?这是与您的系统一起安装的Perl模块吗?是否正确编写,因此它包含 POD 文档。

尝试以下命令:

$ perldoc Taskman::Post

如果此方法有效,它将提取有关如何访问您检索到的此Taskman::Post对象中包含的数据的信息。

如果没有出现,请尝试以下命令:

$ perldoc -l Taskman::Post

这将告诉您是否安装了Taskman :: Post 模块以及它在系统中的位置。您可能必须查看此源以获取它包含的各种方法。这些方法将是该模块内的子程序。以下划线开头的子程序被视为私有,您不应直接使用它们。

如果这不起作用,您需要找到定义此类的位置。有时,人们定义非模块类以在单个程序中使用。例如,我编写了一个程序来跟踪我的员工。我创建了一个Employee类,但不是作为单独的Perl模块安装,而是简单地将它附加到我的Perl程序中。寻找:

package Taskman::Post
代码中的

。如果找到它,请查看代码是否包含 POD 文档。您会在整个文档中看到=pod=head1。如果是这样,你可以尝试:

$ perldoc program.pl

program.pl是你的Perl程序。

回到子程序,你是在写这个类吗?我一直在看$self。这通常意味着您正在使用对象,因此问题是对象的类型是$self。例如,做什么:

print "The reference \$self " . ref( $self ) . "\n";
打印出来?

同样,您不应该操纵对象,就好像它只是对哈希的引用一样。事实上,一些开发人员编写了所谓的inside out类,以防止人们执行Data::Dumper并操纵他们的类而不经过正确的方法。

我发现你的帖子有点令人困惑,因为它听起来像你在编写非面向对象的代码,但你的数据看起来是面向对象的。

您在编写面向对象的代码吗?你知道Perl object oriented programming是如何运作的吗?

如果您正在处理所有内容作为对象。尽量让你的方法理顺。在markup_type子例程中,对象的类型为$self。打印出ref $self并查看它是什么类型的对象。

这应该有助于澄清您正在使用的内容,并且应该帮助您了解您实际提取的内容。

答案 2 :(得分:0)

在我看来,你想要$thing->notice_value(@all_those_arguments)->{VALUE}

这是因为返回值是

{ VALUE => $value,
  OTHERS_POST => $others_post,
  CLIENTS_POST => $clients_post,
  ASSIGNED_TASKS => $assigned_tasks }

$thing->notice_value(@all_those_arguments)只返回此值。这对你有用吗?

相关问题