Đó là bởi vì sẽ mất rất nhiều thời gian và đến một lúc nào đó bạn sẽ có quá nhiều kết hợp mà chúng sẽ không vừa với một mảng.
Mục lục
Bỏ qua mục lục
- Điểm khởi đầu
- phạm vi lỗi
- Tránh RangeErrors
- Nó chậm
- Độ dài của mảng đầu vào vẫn còn hạn chế
- Nghĩ về các lựa chọn thay thế
Điểm khởi đầu
Theo "kết hợp mục mảng", tôi đang đề cập đến bài đăng trên blog của mình từ hôm qua. Tìm tất cả các kết hợp có thể có của các mục mảng trong JS
Đây là mã
const getCombinations = [items] =>
items.reduce[[combos, item] => {
const newCombos = combos.map[[combo] => combo.concat[item]]
combos.push[[item], ...newCombos]
return combos
}, []]
getCombinations[[1, 2, 3]]
//=> [[1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
phạm vi lỗi
Mã ném nếu độ dài của mảng đầu vào quá dài. Trong Firefox giới hạn là 20
getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
- Trong Firefox, thông báo lỗi là "quá nhiều đối số chức năng. "
- Trong Chrome, Edge, Safari và Nút. js, thông báo lỗi là "Vượt quá kích thước ngăn xếp cuộc gọi tối đa. "
Thông báo lỗi của Firefox có vẻ hữu ích hơn vì vấn đề là
getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
1 được gọi với quá nhiều đối số. Trong Firefox, giới hạn là 500.000 mục;[].push[...Array[500_000]] // OK
;[].push[...Array[500_001]] // RangeError
Tránh RangeErrors
Chúng tôi có thể cố gắng tránh vấn đề bằng cách tránh hoàn toàn cú pháp lây lan
const getCombinations = [items] =>
items.reduce[[combos, item] => {
- const newCombos = combos.map[[combo] => combo.concat[item]]
- combos.push[[item], ...newCombos]
+ combos.forEach[[combo] => combos.push[combo.concat[item]]]
+ combos.push[[item]]
return combos
}, []]
[Tôi nghĩ rằng điều này cũng sẽ tăng hiệu suất, nhưng có vẻ như không. Có ý nghĩa mặc dù. chúng tôi tránh lặp qua
getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
2, điều này tốt, nhưng bây giờ chúng tôi đang gọi getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
1 nhiều lần nữa chỉ với một đối số. ]Nó chậm
Giờ đây, các mảng đầu vào lớn hơn hoạt động, nhưng việc kết hợp các mảng đầu vào lớn ngày càng chậm
console.time[]
getCombinations[Array.from[{ length: 20 }]]
console.timeEnd[] //=> ~200ms [on my machine]
console.time[]
getCombinations[Array.from[{ length: 21 }]]
console.timeEnd[] //=> ~400ms [on my machine]
console.time[]
getCombinations[Array.from[{ length: 22 }]]
console.timeEnd[] //=> ~800ms [on my machine]
console.time[]
getCombinations[Array.from[{ length: 23 }]]
console.timeEnd[] //=> ~1800ms [on my machine]
console.time[]
getCombinations[Array.from[{ length: 24 }]]
console.timeEnd[] //=> ~4200ms [on my machine]
Không ai có thời gian để chờ đợi lâu như vậy
Độ dài của mảng đầu vào vẫn còn hạn chế
Trong Firefox, độ dài tối đa của một mảng dường như là
getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
0Array[2 ** 32 - 1] // OK
Array[2 ** 32] // RangeError: invalid array length
Độ dài của mảng được trả về bởi
getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
1 tình cờ là getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
2getCombinations[Array.from[{ length: 1 }]].length === 2 ** 1 - 1 // true
getCombinations[Array.from[{ length: 2 }]].length === 2 ** 2 - 1 // true
getCombinations[Array.from[{ length: 3 }]].length === 2 ** 3 - 1 // true
// ...
getCombinations[Array.from[{ length: 10 }]].length === 2 ** 10 - 1 // true
getCombinations[Array.from[{ length: 11 }]].length === 2 ** 11 - 1 // true
getCombinations[Array.from[{ length: 12 }]].length === 2 ** 12 - 1 // true
// ...and so on
[Bài toán tính tổng các tổ hợp. ]
Nói cách khác, độ dài tối đa của mảng đầu vào là 32
Nhưng các mảng đầu vào dài sẽ không thực tế vì việc nhận tất cả các kết hợp sẽ mất quá nhiều thời gian. Thêm vào đó sẽ có khá nhiều sự kết hợp.
getCombinations[Array.from[{ length: 19 }]] // OK
getCombinations[Array.from[{ length: 20 }]] // RangeError
0 = 4.294.967.295. Hơn 4 tỷNghĩ về các lựa chọn thay thế
Được rồi, vì vậy độ dài của mảng đầu vào được giới hạn ở 32 [ít nhất là trong Firefox] và việc nhận được tất cả các kết hợp sẽ mất nhiều thời gian, vì vậy hãy suy nghĩ