2011-06-08 48 views
0

基于this的帖子,我想了解sort_by如何在JSON::PP中工作。sort_by函数如何工作?

当运行该代码

#!/usr/bin/perl 
use strict; 
use warnings; 
use JSON::PP; 
use Data::Dumper qw(Dumper); 

my $h = { 
    22 => { title => "c", name => "d" }, 
    1 => { title => "1", name => "a" }, 
    10 => { title => "a", name => "c" }, 
    5 => { title => "b", name => "b" }, 
}; 

my $sorter = sub { 
    # See what's going on. 
    print "$JSON::PP::a cmp $JSON::PP::b\n"; 
    print Dumper(\@_, $_); 
    <STDIN>; # press return to continue 

    $JSON::PP::a cmp $JSON::PP::b 
}; 

my $js = JSON::PP->new; 
my $output = $js->sort_by($sorter)->encode($h); 
print $output . "\n"; 

它第一排序的内密钥,然后将外键,其确定在JSON字符串的最后顺序。

现在它输出

{"1":{"name":"a","title":"1"},"10":{"name":"c","title":"a"},"22":{"name":"d","title":"c"},"5":{"name":"b","title":"b"}} 

什么,我想直到结束的是,它是由title即排序。

{"1":{"name":"a","title":"1"},"5":{"name":"b","title":"b"}"10",{"name":"c","title":"a"},"22":{"name":"d","title":"c"}} 

我想第一个问题是禁用最后一个outter键排序?

那么我该如何获得title的价值?算法运行时,$JSON::PP::a$JSON::PP::b包含来自相同散列的值nametitle

这我想不通。任何人都可以解释这一点,和/或帮我写这个算法?

+1

旁注:如果订单真的很重要,我认为你可能应该发送数组而不是对象(好,数组)。这些样品有很多代码味道。 :| – Ashley 2011-06-08 20:45:35

+0

@Ashley:顺序非常重要。如何将我的对象编码到一个对象数组中? – 2011-06-08 21:50:56

+1

您将引用包含散列的数组(并可能将'keys/id'移入散列)。你可能不得不重新安排你的客户端处理,但它比依赖对象/对顺序更有意义,即使在JS中也是如此。你说你想要按“标题”排序的东西,但你想要的输出似乎按“名称”或“键”排序。也许一个新的问题是:服务器上的输入和数据的客户端处理(?)。 – Ashley 2011-06-08 22:16:49

回答

2

你不能,或者至少不容易。您给sort_by的功能只能访问正在排序的键。为了做你想做的事,你需要访问与这些键相关的值(或者更可能的是,键所属的hashref,以便你可以自己查找这些值)。这似乎是一个有益的增强;您可能会提交功能请求。

如果您的数据结构足够简单(您的示例似乎是),那么您可以自己保留对散列的引用。为了做到这一点,你必须能够区分内部哈希中的键和外部哈希中的键(这样你就知道哪个哈希正在被排序,从而进行什么样的比较)。

my $sorter = sub { 
    if ($JSON::PP::a =~ /^\d+$/) { 
     return $h->{$JSON::PP::a}{title} cmp $h->{$JSON::PP::b}{title}; 
    } 
    return $JSON::PP::a cmp $JSON::PP::b 
}; 
1

尝试类似:

my $sorter = sub { 
    my $h = $_[0]; 

    # simple check for if we are too deep 
    # just sort by keys in that case 
    return $JSON::PP::a cmp $JSON::PP::b 
     if ref($h->{$JSON::PP::a}) ne 'HASH'; 

    # sort by titles value 
    return $h->{$JSON::PP::a}{title} cmp $h->{$JSON::PP::b}{title}; 
}; 

$_[0]目前正在整理散,本书虽然这似乎并没有被记录(因此可能是不可靠的)。

它适用于这种情况,但更复杂的结构会有问题,因为深度检查非常简单。如果你确定不存在这种类型的更深的键,那么对cjm这样的键类型的检查会更好。或者组合,如:

my $sorter = sub { 
    my $h = $_[0]; 

    # just sort by the keys 
    return $JSON::PP::a cmp $JSON::PP::b 
     unless $JSON::PP::a =~ /^\d+\z/ 
      && $JSON::PP::b =~ /^\d+\z/ 
      && ref($h->{$JSON::PP::a}) eq 'HASH' 
      && ref($h->{$JSON::PP::b}) eq 'HASH'; 

    # sort by titles 
    return $h->{$JSON::PP::a}{title} cmp $h->{$JSON::PP::b}{title}; 
}; 
+1

“$ _ [0]是当前正在排序的哈希”实际上是两个级别的无证行为。首先,当比较子程序没有原型时,Perl的'sort'不会改变@ @'。其次,JSON :: PP将散列作为第一个参数传递给它的'_sort'子例程。我会犹豫依靠所有这一切。 – cjm 2011-06-08 21:26:54

+0

你写'cmd'而不是'cmp'。我能理解为什么=) – 2011-06-08 21:47:11