2010-07-09 39 views
7

Tôi có mảnh này của kịch bản:hành vi kỳ lạ của loại

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my @arr = (
    { 
     name => 'foo', 
     value => 123, 
    }, 
    { 
     name => 'bar', 
     value => 'nan', 
    }, 
    { 
     name => 'foobar', 
     value => 456, 
    }, 
); 

@arr = sort {$a->{value} <=> $b->{value} } @arr; 

print Dumper(\@arr); 

tôi không có bất kỳ vấn đề hệ điều hành Windows XP/Strawberry Perl 5.10.1

hoặc Linux 2.6.12-1 i386/Perl v5.8.5 xây dựng cho i386-linux-thread-đa,

nhưng dưới Linux 2.6.18-53/Perl v5.8.8 xây dựng cho x86_64-linux-thread-đa, tôi đã nhận được thông báo lỗi:

Sort subroutine didn't return a numeric value at testsort.pl line 21. 

Có gì không ổn và tôi có thể sửa nó như thế nào?

+0

Điều tương tự có xảy ra nếu bạn đơn giản hóa nó như thế này không? @arr = sắp xếp {$ a <=> $ b} (123, 'nan', 456); – wdebeaum

+0

@wdebeaum: không có lỗi trong một lớp lót nhưng không sắp xếp bất kỳ điều gì dưới x86_64 trong khi nó ok trong win XP và i386 – Toto

Trả lời

6

Trong một số bản dựng, 'nan' được ép buộc thành số 0 cho so sánh <=> và sắp xếp thành công. Trong các bản dựng khác, nan được coi là "không phải là số" và giá trị trả lại từ <=> không được xác định.

Đối với tính di động tối đa, kiểm tra giá trị cho dù đó là một số lượng tốt của không:

(isnan chương trình con từ How do I create or test for NaN or infinity in Perl?):

sub isnan { ! defined($_[0] <=> 9**9**9) } 

@arr = sort { isnan($a->{value}) ? 0 : $a->{value} 
         <=> 
       isnan($b->{value}) ? 0 : $b->{value} } @arr; 
+0

Nó hoạt động. Tôi đã bao quanh ternary bằng dấu ngoặc đơn. – Toto

4

2 Solutions

  1. mobrule Giải pháp của:

    sub isnan { ! defined($_[0] <=> 9**9**9) } 
    @arr = sort { isnan($a->{value}) ? 0 : $a->{value} 
               <=> 
           isnan($b->{value}) ? 0 : $b->{value} } @arr; 
    
  2. Perldoc 's giải pháp:

    @result = sort { $a <=> $b } grep { $_ == $_ } @input; 
    

  1. Cho NaN một giá trị 0 của bạn, mà nên đẩy nó lên đầu danh sách.
  2. Tận dụng lợi thế NaN != NaN, để loại bỏ bất kỳ NaN giây nào từ danh sách nhập.

Như mobrule tuyên bố, điều này được gây ra bởi sự so sánh giữa NaN xây dựng.