Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add product function #377

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Add product function #377

wants to merge 1 commit into from

Conversation

dolsem
Copy link

@dolsem dolsem commented Feb 16, 2024

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

  • Changes are covered by tests if behavior has been changed or added
  • Tests have 100% coverage
  • If code changes were made, the version in package.json has been bumped (matching semver)
  • If code changes were made, the yarn build command has been run and to update the cdn directory
  • If code changes were made, the documentation (in the /docs directory) has been updated

Resolves

If the PR resolves an open issue tag it here. For example, Resolves #34

Copy link

vercel bot commented Feb 16, 2024

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
@aleclarson
Copy link

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.

@BarleyBig
Copy link

BarleyBig commented Aug 21, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants