2011-06-08 71 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