cross.js 872 B

123456789101112131415161718192021222324252627282930313233
  1. function length(array) {
  2. return array.length | 0;
  3. }
  4. function empty(length) {
  5. return !(length > 0);
  6. }
  7. function arrayify(values) {
  8. return typeof values !== "object" || "length" in values ? values : Array.from(values);
  9. }
  10. function reducer(reduce) {
  11. return values => reduce(...values);
  12. }
  13. export default function cross(...values) {
  14. const reduce = typeof values[values.length - 1] === "function" && reducer(values.pop());
  15. values = values.map(arrayify);
  16. const lengths = values.map(length);
  17. const j = values.length - 1;
  18. const index = new Array(j + 1).fill(0);
  19. const product = [];
  20. if (j < 0 || lengths.some(empty)) return product;
  21. while (true) {
  22. product.push(index.map((j, i) => values[i][j]));
  23. let i = j;
  24. while (++index[i] === lengths[i]) {
  25. if (i === 0) return reduce ? product.map(reduce) : product;
  26. index[i--] = 0;
  27. }
  28. }
  29. }