2011-01-12 35 views
8

Đây là câu hỏi chi tiết về triển khai cho các chuyên gia JavaScript.Triển khai bảng quyết định phức tạp trong JavaScript

Tôi có giao diện người dùng với một số trường trong đó giá trị của các trường phụ thuộc vào thời trang phức tạp trên các giá trị của bảy bit đầu vào. Chính xác những gì sẽ được hiển thị cho bất kỳ một trong 128 giá trị có thể thay đổi thường xuyên khi người dùng thấy nhiều ứng dụng hơn?

Ngay bây giờ, tôi đã thực hiện điều này như một cây quyết định thông qua một cái lược nếu-thì-khác, nhưng nó giòn theo yêu cầu thay đổi và loại khó để có được quyền.

cách tiếp cận Một thực hiện tôi đã nghĩ đến việc là làm cho một mảng các giá trị từ 0x0 đến 0x7F và sau đó lưu trữ một đóng cửa tại mỗi địa điểm -

var tbl; // initialize it with the values 
    ... 
tbl[0x42] = function(){ doAThing(); doAnotherThing(); } 

và sau đó gọi chúng với

tbl[bitsIn](); 

Điều này, ít nhất làm cho logic quyết định thành một loạt các bài tập.

Câu hỏi: có cách nào tốt hơn không?

(Cập nhật: Holy crap, Sao mà dòng về 'thẻ iphone ajax' get trong đó Không ngạc nhiên đó là một khó hiểu chút.)

Cập nhật

Vậy điều gì đã xảy ra ? Về cơ bản tôi đã lựa chọn thứ tư, mặc dù tương tự như tôi đã kiểm tra. Logic là đủ phức tạp mà cuối cùng tôi đã xây dựng một chương trình Python để tạo ra một bảng chân lý trong máy chủ (tạo mã Groovy, trên thực tế, máy chủ là một ứng dụng Grails) và chuyển logic quyết định vào máy chủ hoàn toàn. Bây giờ phía JavaScript đơn giản là diễn giải một đối tượng JSON chứa các giá trị cho các trường khác nhau.

Cuối cùng, điều này có thể sẽ trải qua một lần lặp lại khác và trở thành dữ liệu trong một bảng cơ sở dữ liệu, được lập chỉ mục bằng vectơ của các bit.

Phần điều khiển bảng chắc chắn là một cách để đi; đã có một nửa tá mới thay đổi trong các yêu cầu cụ thể để hiển thị.

+2

Từ những gì tôi hiểu về vấn đề của bạn, những suy nghĩ của bạn là sắp xếp âm thanh, nhưng tbh i không chắc chắn từ mô tả của bạn, bạn cần gì: P –

+0

Mỗi bit có xác định một hành động cụ thể không? Nếu vậy, tại sao không thực hiện bitwise AND trên giá trị của bạn so với [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40] – draeton

+0

@Martin, vấn đề là liệu có cách nào khác, linh hoạt hơn, cách thực hiện điều này hơn bảng của tôi của lambdas. –

Trả lời

1

Bạn đã cân nhắc tạo cây quyết định trên máy chủ chứ không phải viết bằng tay? Sử dụng bất kỳ đại diện là sạch sẽ, dễ dàng để làm việc với, và sửa đổi và sau đó biên dịch mà javascript xấu xí nhưng hiệu quả cho phía khách hàng.

Cây quyết định khá dễ dàng để thể hiện dưới dạng dữ liệu và dễ hiểu và làm việc với cấu trúc dữ liệu cây truyền thống. Bạn có thể lưu trữ cây đã nói dưới mọi hình thức có ý nghĩa với bạn. Việc xác thực và sửa đổi nó dưới dạng dữ liệu cũng nên được chuyển tiếp thẳng.

Sau đó, khi bạn cần sử dụng cây quyết định, chỉ cần biên dịch/tuần tự hóa nó thành JavaScript như một sự lộn xộn lớn nếu-người khác, chuyển đổi hoặc băm. Điều này cũng nên được khá thẳng về phía trước và có lẽ dễ dàng hơn nhiều so với cố gắng để duy trì một switch với một vài trăm yếu tố.

2

Vì tình huống (như bạn đã mô tả) quá bất thường nên dường như không có cách nào tốt hơn. Mặc dù, tôi có thể đề xuất cải tiến cho bảng nhảy của bạn. Bạn đã đề cập rằng bạn có lỗi và trùng lặp. Vì vậy, thay vì chỉ định rõ ràng chúng cho việc đóng cửa, bạn có thể gán chúng cho các hàm được đặt tên để bạn không phải lặp lại việc đóng cửa rõ ràng.

var doAThingAndAnother = function(){ doAThing(); doAnotherThing(); } 

var tbl; // initialize it with the values 
    ... 
tbl[0x42] = doAThingAndAnother; 
tbl[0x43] = doAThingAndAnother; 

Không có nhiều cải tiến, nhưng đó là điều duy nhất tôi có thể nghĩ đến! Bạn dường như đã bao phủ hầu hết các vấn đề khác. Vì có vẻ như các yêu cầu thay đổi rất nhiều, tôi nghĩ bạn có thể phải từ bỏ sự sang trọng và có một thiết kế không thanh lịch, nhưng vẫn dễ thay đổi.

5

Tôi thấy hai tùy chọn ...

chung cho cả hai giải pháp là các chức năng có tên sau đây:

function aThing() {} 
function anotherThing() {} 
function aThirdThing() {} 

Cách chuyển đổi

function exec(bits) { 
switch(bits) { 
    case 0x00: aThing(); anotherThing(); break; 
    case 0x01: aThing(); anotherThing(); aThirdThing(); break; 
    case 0x02: aThing(); aThirdThing(); break; 
    case 0x03: anotherThing(); aThirdThing(); break; 
    ... 
    case 0x42: aThirdThing(); break; 
    ... 
    case 0x7f: ... break; 
    default: throw 'There is only 128 options :P'; 
    } 
} 

Bản đồ đường

function exec(bits) { 
    var actions = map[bits]; 
    for(var i=0, action; action=actions[i]; i++) 
     action(); 
} 

var map = { 
0x00: [aThing, anotherThing], 
0x01: [aThing, anotherThing, aThirdThing], 
0x02: [aThing, aThirdThing], 
0x03: [anotherThing, aThirdThing], 
    ... 
0x42: [aThirdThing], 
    ... 
}; 

trong cả hai trường hợp, bạn muốn gọi

exec(0x42); 
+0

không thể vòng lặp đó là hành động 'for (var action in actions)();'? –

+0

Nó có thể nhưng sẽ làm cho ít ý nghĩa. Các hành động trong trường hợp này là một mảng các tham chiếu hàm và bạn không muốn lặp qua các mảng với (var i in array) vì nó chậm hơn nhiều và vì nó sẽ cho bạn kết quả không đồng đều trên các trình duyệt. Một số trình duyệt sẽ xử lý thuộc tính "length" trên mảng như là một thành viên khác của đối tượng và cung cấp cho bạn điều đó cũng như các tham chiếu hàm. –

+0

[] .propertyIsEnumerable ('length') === false – draeton

1

Tôi đã có một ví dụ thô của một công cụ cây quyết định JavaScript nếu bạn muốn có một cái nhìn:

http://jsfiddle.net/danw/h8CFe/

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