2013-09-23 27 views
6

Tôi cần tạo một tập hợp đầy đủ các biến thể dựa trên danh sách N thuộc tính, trong khi vẫn giữ nguyên tên thuộc tính.Sản phẩm Descartes của các đối tượng trong javascript

var input = [ 
    { 'colour' : ['red', 'green'] }, 
    { 'material' : ['cotton', 'wool', 'silk'] }, 
    { 'shape' : ['round', 'square', 'rectangle'] } 
]; 

var expected = [ 
    { 'colour': 'red', 'material': 'cotton', 'shape': 'round' }, 
    { 'colour': 'red', 'material': 'cotton', 'shape': 'square' }, 
    { 'colour': 'red', 'material': 'cotton', 'shape': 'rectangle' }, 
    { 'colour': 'red', 'material': 'wool', 'shape': 'round' }, 
    { 'colour': 'red', 'material': 'wool', 'shape': 'square' }, 
    { 'colour': 'red', 'material': 'wool', 'shape': 'rectangle' }, 
    { 'colour': 'red', 'material': 'silk', 'shape': 'round' }, 
    { 'colour': 'red', 'material': 'silk', 'shape': 'square' }, 
    { 'colour': 'red', 'material': 'silk', 'shape': 'rectangle' }, 
    { 'colour': 'green', 'material': 'cotton', 'shape': 'round' }, 
    { 'colour': 'green', 'material': 'cotton', 'shape': 'square' }, 
    { 'colour': 'green', 'material': 'cotton', 'shape': 'rectangle' }, 
    { 'colour': 'green', 'material': 'wool', 'shape': 'round' }, 
    { 'colour': 'green', 'material': 'wool', 'shape': 'square' }, 
    { 'colour': 'green', 'material': 'wool', 'shape': 'rectangle' }, 
    { 'colour': 'green', 'material': 'silk', 'shape': 'round' }, 
    { 'colour': 'green', 'material': 'silk', 'shape': 'square' }, 
    { 'colour': 'green', 'material': 'silk', 'shape': 'rectangle' } 
]; 

Có rất nhiều thuật toán xung quanh cho các sản phẩm tiêu chuẩn của mảng, nhưng tôi dường như không tìm thấy thuật toán nào cho các đối tượng bảo tồn khóa.

Hiệu suất không phải là mối lo ngại lớn vì sẽ không bao giờ có nhiều hơn một tá giá trị cho mỗi thuộc tính. Đơn đặt hàng không phải khớp chính xác với số expected.

Tôi đã thực hiện một nỗ lực ban đầu dựa trên các thuật toán tiêu chuẩn cho các danh sách, nhưng tôi đang gặp khó khăn:

function cartesianProduct(input, current) { 
    if (!input || input.length < 1) { 
     return []; 
    } 

    var head = input[0]; 
    var tail = input.slice(1); 
    var output = []; 

    for (var key in head) { 
     for (var i = 0; i < head[key].length; i++) { 
      if (typeof current == 'undefined') { 
       var current = {}; 
      } 

      current[key] = head[key][i]; 
      var productOfTail = cartesianProduct(tail, current); 
      output.push(current); 
      console.log(current); 
     } 
    } 

    return output; 
} 

console.log(cartesianProduct(input)); 
+0

[Câu hỏi tương tự đã được hỏi tại đây] (http://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in -javascript) – Keithamus

+0

có một vấn đề lớn trong mã của bạn: bạn không khai báo i là var, vì vậy nó được coi là var toàn cục, do đó thay đổi d trong các chức năng bên trong cuộc gọi ... – GameAlchemist

Trả lời

4

Khi bạn thoát khỏi ' 'i' là một vấn đề toàn cầu var', bạn có thể nhận được kết quả với mã này ví dụ:

var input = [ 
    { 'colour' : ['red', 'green'] }, 
    { 'material' : ['cotton', 'wool', 'silk'] }, 
    { 'shape' : ['round', 'square', 'rectangle'] } 
]; 

function cartesianProduct(input, current) { 
    if (!input || !input.length) { return []; } 

    var head = input[0]; 
    var tail = input.slice(1); 
    var output = []; 

    for (var key in head) { 
     for (var i = 0; i < head[key].length; i++) { 
      var newCurrent = copy(current);   
      newCurrent[key] = head[key][i]; 
      if (tail.length) { 
       var productOfTail = 
         cartesianProduct(tail, newCurrent); 
       output = output.concat(productOfTail); 
      } else output.push(newCurrent); 
     } 
    }  
    return output; 
} 

function copy(obj) { 
    var res = {}; 
    for (var p in obj) res[p] = obj[p]; 
    return res; 
} 


console.log(cartesianProduct(input)); 
+0

Chúc mừng cho rằng, tôi biết có một vấn đề với đẩy hiện tại để mảng đầu ra nhưng không thể làm việc ra lý do tại sao. –

+0

Bạn được chào đón. Như bạn đã hiểu, mà không cần sao chép, bạn tiếp tục thay đổi một đối tượng duy nhất trong mỗi cuộc gọi đệ quy, do đó sản phẩm không hoạt động. – GameAlchemist

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