基于this帖子,我试图了解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
包含来自同一哈希的值name
和title
。
我无法弄明白。任何人都可以解释这个,和/或帮我写这个算法吗?
答案 0 :(得分: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 :(得分: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};
};