2012-05-31 27 views
9

Làm thế nào tôi có thể bình thường hóa một danh sách các đối số hàm thành một chuỗi, sao cho hai danh sách đối số chuyển đổi thành cùng một chuỗi iff chúng có hiệu quả tương đương? Thuật toán nênLàm thế nào để chuẩn hóa các đối số hàm Perl để ghi nhớ?

  1. Hãy so sánh băm nhúng và danh sách sâu sắc, chứ không phải bằng cách tham khảo
  2. Bỏ qua băm để chìa khóa
  3. Bỏ qua sự khác biệt giữa 3 và "3"
  4. Tạo một chuỗi tương đối dễ đọc (không bắt buộc, nhưng đẹp-to-có cho gỡ lỗi)
  5. Thực hiện tốt (XS ưa thích hơn Perl)

này là cần thiết cho memoization, tức là lưu vào bộ nhớ đệm kết quả của hàm dựa trên các đối số của nó.

Như một ví dụ strawman, Memoize sử dụng điều này như một normalizer mặc định, mà thất bại # 1 và # 3:

$argstr = join chr(28),@_; 

Trong một thời gian tôi đi đến normalizer là

JSON::XS->new->utf8->canonical 

Tuy nhiên nó xử lý số 3 và chuỗi "3" differently, dựa trên cách sử dụng vô hướng gần đây. Điều này có thể tạo ra các chuỗi khác nhau cho các danh sách đối số cơ bản tương đương và giảm lợi ích ghi nhớ. (. Phần lớn các chức năng sẽ không biết hoặc quan tâm nếu họ nhận được 3 hoặc "3")

Đối với niềm vui Tôi nhìn một loạt các serializers để xem cái nào phân biệt 3 và "3":

Data::Dump : equal - [3] vs [3] 
Data::Dumper : not equal - [3] vs ['3'] 
FreezeThaw : equal - FrT;@1|@1|$1|3 vs FrT;@1|@1|$1|3 
JSON::PP  : not equal - [3] vs ["3"] 
JSON::XS  : not equal - [3] vs ["3"] 
Storable  : not equal - <unprintable> 
YAML   : equal - ---\n- 3\n vs ---\n- 3\n 
YAML::Syck : equal - --- \n- 3\n vs --- \n- 3\n 
YAML::XS  : not equal - ---\n- 3\n vs ---\n- '3'\n 

Trong số những báo cáo "bằng", không chắc chắn cách làm cho chúng bỏ qua thứ tự khóa băm.

Tôi có thể đi trước danh sách đối số trước và xâu chuỗi tất cả các số, nhưng điều này sẽ yêu cầu tạo bản sao sâu và vi phạm # 5.

Cảm ơn!

+0

Ngoài ra còn có [Test :: More] (http://metacpan.org/module/Test::More) 's is_deeply và [Test :: Deep] (http://metacpan.org/module/Test :: Deep) của eq_deeply. – Ether

Trả lời

2

Khá nhiều bộ nối tiếp sẽ xử lý 3 và "3" khác nhau, bởi vì nó không có kiến ​​thức về số và số được xâu chuỗi giống nhau cho bạn và giả định này là sai cho dữ liệu chung. Bạn phải chuẩn hóa đầu vào hoặc đầu ra cho chính mình.

Để nhập, quét sâu bằng cách thay thế bất kỳ số được xâu chuỗi nào có giá trị bằng 0 sẽ làm. Nếu bạn biết chính xác số điện thoại có thể ở đâu, bạn có thể rút ngắn quá trình quét này một cách đáng kể.

Đối với đầu ra, một số máy trạng thái đơn giản hoặc thậm chí regexp (có, tôi biết rằng đầu ra là không thường xuyên) sẽ có khả năng đủ để loại bỏ các giá trị chuỗi chỉ số thành số.

+0

Vâng, không, tôi liệt kê một số serializers ở trên (như Data :: Dump và FreezeThaw) mà không. :) Có lẽ bạn có nghĩa là "bất kỳ serializer tốt * nên * điều trị 3 và" 3 "khác nhau". Tôi không chắc chắn như vậy, với sự dễ dàng và tùy tiện với giá trị Perl có thể bỏ qua giữa chuỗi và số. –

+0

Quét lại, tôi đã đề cập rằng quá trình quét đầu vào là không mong muốn vì hiệu suất. Nếu nó phải được thực hiện, tôi muốn nó được trong XS. Nhưng nó sẽ hiệu quả hơn nhiều nếu serializer có một tùy chọn để chỉ cần tắt sự khác biệt. –

+0

Làm thế nào về quét đầu ra tôi đã đề cập sau đó? Điều này phải đủ nhanh. Một điểm cộng quan trọng khi so sánh với tùy thuộc vào các quirks không có giấy tờ là bạn luôn có thể chắc chắn rằng các giá trị bị tước bằng tay thực sự sẽ bị tước bỏ. –

2

YAML và các khóa băm phân loại tiền tố theo mặc định. Đặt $YAML::SortKeys = 2 để sắp xếp trên băm sâu.

Đặt $YAML::Stringify thành giá trị thực và đặt $YAML::XS::QuoteNumericStrings thành giá trị sai sẽ giúp bạn chuẩn hóa giá trị số. Cài đặt thứ hai sẽ "unquote" một giá trị chuỗi trông giống như một số.


Ngoài ra, bạn có thể sử dụng $Data::Dumper::Sortkeys = 1 để chuẩn hóa thứ tự đầu ra với Data::Dumper. Đặt $Data::Dumper::Useqq = 1 sẽ hủy các chuỗi trông giống như số.

+0

Xin lỗi, nhưng không, YAML :: XS sẽ hoạt động giống như bất kỳ serializer nào. Hãy thử 'perl -MYAML :: XS -e 'my $ v =" 0333 "; in YAML :: XS :: Dump $ v; $ v + 0; in YAML :: XS :: Dump $ v; in "$ v \ n"; '' –

+0

@Oleg V. Volkov - nhờ lời nhận xét của bạn, tôi đã tìm hiểu thêm về những gì' $ YAML :: XS :: QuoteNumericStrings' là dành cho và chỉnh sửa câu trả lời của tôi. Nhưng tôi nghĩ rằng "0333" 'và' "333" 'và' 0333' (tức là 219) nên được OP coi là các đầu vào khác nhau. – mob

+0

Chỉ cần "333" sẽ hoạt động giống hệt nhau. –

Các vấn đề liên quan