Add product function
Description
This PR adds a product function that takes N arrays as arguments and outputs the Cartesian product, for example:
produce(['a', 'b'], [1, 2]) // => [['a', 1], ['a', 2], ['b', 1], ['b', 2]]
Checklist
- [x] Changes are covered by tests if behavior has been changed or added
- [x] Tests have 100% coverage
- [ ] If code changes were made, the version in
package.jsonhas been bumped (matching semver) - [ ] If code changes were made, the
yarn buildcommand has been run and to update thecdndirectory - [x] If code changes were made, the documentation (in the
/docsdirectory) has been updated
Resolves
If the PR resolves an open issue tag it here. For example, Resolves #34
The latest updates on your projects. Learn more about Vercel for Git ↗︎
| Name | Status | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| radash-docs | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Feb 16, 2024 3:44am |
Hey @dolsem, we might be interested in merging this over at the Radashi fork. You're invited to re-submit this PR there, but please specify how you use this function. 😄
P.S. You can read my post to learn more about the differences between Radashi and its predecessor.
Hey @dolsem I found your Cartesian product function code, Is very beautifully and has extremely high performance. I think we can do some more optimization.
Cartesian product generally generates a relatively long result array, and the array size may be adjusted many times during the process. We can completely pre-calculate the length of the result array and initialize it,
like this:
const result = new Array(arrays.reduce((pre, curr) => pre * curr.length, 1));
indices init can be simpler and faster. Using const indices = arrays.map(() => 0) will be faster than new Array(arrays.length).fill(0) 。
The complete example is as follows:
export function product(arrays) {
if (!arrays || !arrays.length || arrays.some(p => p.length < 1)) {
return [];
}
const indices = arrays.map(() => 0)
let currentIndex = arrays.length - 1;
let resultIndex = 0
const result = new Array(arrays.reduce((pre, curr) => pre * curr.length, 1));
while (indices[0] < arrays[0].length) {
result[resultIndex] = indices.map((j, i) => arrays[i][j])
indices[currentIndex] += 1;
while (currentIndex > 0 && indices[currentIndex] === arrays[currentIndex].length) {
indices[currentIndex] = 0;
indices[currentIndex - 1] += 1;
currentIndex -= 1;
}
currentIndex = arrays.length - 1;
resultIndex++
}
return result;
}
I ran some benchmarks and found it to be nearly 10% faster。 Thank you for creating such a useful function. I look forward to hearing your thoughts.
A similar implementation is being developed at this PR: https://github.com/radashi-org/radashi/pull/241