GithubHelp home page GithubHelp logo

jankapunkt / js-set-extension Goto Github PK

View Code? Open in Web Editor NEW
13.0 4.0 3.0 1.17 MB

Extending the Set class in order to support mathematical set properties and operations.

Home Page: https://www.npmjs.com/package/set-extensions

License: MIT License

JavaScript 100.00%
javascript set set-theory math union intersection subset superset difference complement symmetric-difference powerset proper-subset proper-superset hacktoberfest

js-set-extension's Introduction

Javascript Set Extensions

Polyfill for extending the Javascript Set class in order to support properties and operations from basic set theory.

Test suite CodeQL Semantic Analysis Project Status: Active โ€“ The project has reached a stable, usable state and is being actively developed. JavaScript Style Guide npm bundle size GitHub

Scope

Please read this first, to a get a better understanding, whether this package suits your needs.

Completeness vs. Performance

Focus of this package is to provide a Set implementation, which can be used in context of axiomatic set theory.

Set's class Methods are primarily designed to

  • run with any values, but also values as Sets (of Sets, arbitrary depth)
  • work with arbitrary (but finite) numbers of sets (depending on operation, see documentation)
  • conform with their respective properties (Associative, Commutative etc.)
  • don't mutate any of the given but return a new Set as result

Set's prototype Methods are in contrast designed to work as a binary operation on the current instance but they also won't mutate any of the involved Sets.

Some algorithms may grow exponentially with a raising number of sets to be processes. Please, see the documentation notes on the respective methods.

Extending Set

This package builds upon the Set implementation, instead of providing an own. Some suggest it's bad design to extend core implementations.

However, the core functionality of Set is stable and proven and this package tries to be minimally invasive on the Set implementation.

Please, leave an issue, in case this extension breaks your setup by whatever unexpected or undefined behaviour.

Future Implementations

Currently, this package only supports finite sets. A future implementation could include generators to support infinite sets and function-based operations with infinite sets. Ideas.concepts and contributions are very welcomed.

Installation and Usage

Install this package as usual:

$ npm install --save set-extensions

Import this package in your startup code. The package automatically extends the global Set object.

import 'set-extensions'

You can verify the presence of this polyfill by checking for the __isExtended__ property:

Set.__isExtended__ // true if this package is installed

API Documentation

There is a markdown version and a html version of the API documentation. If you think this documentation can be improved, please leave a pull request or open an issue.

Run the tests

Add the description about testing in the README:

You can run the tests like the following:

$ cd js-set-extension/package
$ npm install

To run tests in watch mode use

$ npm run test-watch

or for a single run use

$ npm run test

The tests are written in mocha but it should not be that hard to get into it as it is written very intuitive.

Linter

Please note, that the tests are very strict about code style and you can check for code style related errors using

npm run lint

You should fix these lint errors, since the CI server will reject to run any tests when the linter as thrown an error.

You can also run lint and tests all in one process using

npm run lint-test

The scripts to run these commands are also in the package.json file:

https://github.com/jankapunkt/js-set-extension/blob/master/package/package.json

License

MIT

js-set-extension's People

Contributors

dependabot[bot] avatar eriice avatar jankapunkt avatar mareoraft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

js-set-extension's Issues

Version 2

I'm not sure how you want to deal with all these breaking changes (due to name changes of some of the functions).

I might suggest that we start a new branch (called "version2" or similar) and make our PR's to that branch instead. In a month or so when all of our desired changes are done, you may choose to "release" version 2 to the master branch. Breaking changes usually warrant an increment of the major version number.

To make the transition easier, you can make the old function names aliases to the new function names, for backwards compatibility. That could be accompanied with a warning and deprecation message. Whatever you prefer.

For now I will continue making my PR's to the master branch, until you let me know otherwise.

intersections

There needs to be a boolean operation on instances of Sets that allow the following:

What you say: "The intersection of M"
What you type: Set.intersection(M)
ref: https://en.wikipedia.org/wiki/Intersection_(set_theory)#Arbitrary_intersections
description: The arbitrary intersection operator acts on any iterable (of sets) and returns a single set whose elements consist of the elements that occur in every single set in the iterable.
note: (*)
note: the function should be able to take in an iterable of length 0 or 1.

  • Set.intersection([A]) should output A.
  • Set.intersection([]) should output the entire universe (but we don't have a global "universe" right now, so for now we should throw an error).

What you say: "The intersection of A and B" or "A intersect B"
What you type: A.intersect(B)
ref: https://en.wikipedia.org/wiki/Intersection_(set_theory)#Definition
description: The small intersection operator is a binary operator which takes in two sets.

suggested Set implementation for JS 5

If I'm using JS 5 but I want the JS 6 style Set class, is there a recommended way / library for including that class into my JS 5 project?

I'm running into a situation where I really want the set datatype at work, but we are stuck with a JavaScript engine that only runs JS 5. I was wondering if you happened to know. Ideally, such a Set class would:

  • be as close to the JS 6 Set class as possible
  • could be extended with js-set-extension

proposal for naming conventions

The following is a proposal for naming conventions of set operations (As always, there are no worries if you disagree, and everything is open to discussion).

I propose that the API/usage should match how the operation is phrased in mathematics in english. So what you say determines the naming/syntax. Also, I take into account that boolean functions are usually used in the context of if-statements.

Example

What you say: "if A is a superset of B, ..."
What you type: if (A.isSuperset(B)) {

Proposed Naming Conventions

containment

What you say: "if A is a proper superset of B, ..."
What you type: if (A.isProperSuperset(B)) {
note: After some nail biting, I settled on the word 'of' being builtin to functions. We say "f of x" and we write "f(x)". We don't write the of, but instead it is as-if the open-parenthesis is the of.

What you say: "if A is a proper subset of B, ..."
What you type: if (A.isProperSubset(B)) {

equality

What you say: "if A is equal to B, ..." or "if A equals B, ..."
What you type: if (A.equals(B)) {

unions

What you say: "The union of M"
What you type: Set.union(M)
ref: https://en.wikipedia.org/wiki/Union_(set_theory)#Arbitrary_unions
description: The arbitary union operator acts on any iterable (of sets) M and returns a single set whose elements consist of the elements of each set in the iterable.
note: Throws an error if you don't give it exactly 1 argument
note: Throws an error if the input is not an iterable of sets
note: The above two notes will be referred to as (*), to avoid repetition below.

What you say: "The union of A and B" or "A union B"
What you type: A.union(B)
ref: https://en.wikipedia.org/wiki/Union_(set_theory)#Union_of_two_sets
description: The small union operator is a binary operator which takes in two sets.
note: (*)
note: the function should be able to take in an iterable of length 0 or 1.

  • Set.union([A]) should output A.
  • Set.union([]) should output the empty set.

intersections

What you say: "The intersection of M"
What you type: Set.intersection(M)
ref: https://en.wikipedia.org/wiki/Intersection_(set_theory)#Arbitrary_intersections
description: The arbitrary intersection operator acts on any iterable (of sets) and returns a single set whose elements consist of the elements that occur in every single set in the iterable.
note: (*)
note: the function should be able to take in an iterable of length 0 or 1.

  • Set.intersection([A]) should output A.
  • Set.intersection([]) should output the entire universe (but we don't have a global "universe" right now, so for now we should throw an error).

What you say: "The intersection of A and B" or "A intersect B"
What you type: A.intersect(B)
ref: https://en.wikipedia.org/wiki/Intersection_(set_theory)#Definition
description: The small intersection operator is a binary operator which takes in two sets.

differences

What you say: "The set difference of A and B"
What you type: Set.difference(A, B)
note: no change

What you say: "A minus B"
What you type: A.minus(B)
description: This is the same as the difference operator, but with a different syntax.

What you say: "The symmetric difference of M"
What you type: Set.symmetricDifference(M)
ref: https://en.wikipedia.org/wiki/Symmetric_difference#n-ary_symmetric_difference
description: The repeated symmetric difference, as described in ref above.
note: This function should be able to take in an iterable of length 0 or 1.

  • Set.symmetricDifference([A]) should output A.
  • Set.symmetricDifference([]) should output the empty set.

What you say: "The symmetric difference of A and B"
What you type: A.symmetricDifference(B)
ref: https://en.wikipedia.org/wiki/Symmetric_difference
description: A triangle B.

products

What you say: "The cartesian product of M"
What you type: Set.cartesianProduct(M)
description: Perform the n-ary cartesian product (aka the n-fold cartesian product) of all the sets in X
example:

  • Set.cartesianProduct([A, B, C]) should output the set whose elements anything of the form (a, b, c) where a is in A, b is in B, and c is in C.
    note: Note that A.cartesianProduct(B).cartesianProduct(C) is NOT the same as Set.cartesianProduct([A, B, C]).

What you say: "The cartesian product of A and B"
What you type: A.cartesianProduct(B)
ref: https://en.wikipedia.org/wiki/Cartesian_product
description: the binary operation version.

power set

What you say: "The power set of A" or "The set of subsets of A"
What you type: Set.powerSet(A)
note: I have always heard people always say "the power set of A", but never "the power of A". Hence, I believe truncating the function name to only "power" would cause confusion, since the term "power" can mean so many different things.

In conclusion

Almost every set operation (with the exception of the difference operation, since it is not symmetric) has both a "binary operation version" (such as "A triangle B" or A.triangle(B)) and an "arbitrary operation version" (such as "triangle M" or Set.triangle(M)). Our syntax reflects this.

question about your documentation tool(s)

By the way, I see you have docstrings like

/**
 * Adds a value to the set. If the set already contains the value, nothing happens.
 * Overrides Set.prototype.add.
 * @name Set.prototype.add
 * @function
 * @throws Error if rules function exists and {value} failed the rules check.
 * @param value {*}- Required. Any arbitrary value to be added to the set.
 * @returns {Set} the Set object
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add
 */

in your code. Is there a specific tool you use to generate these? And is there a tool that produces documentation from these comments? I'm considering using this as I grow my JavaScript skills. I lack good documentation tools. Any recommendations are appreciated!

P.S. Let me know if you'd prefer me not posting off-topic questions such as these, or if you prefer I send them to a different place.

Union

What you say: "The union of M"
What you type: Set.union(M)
ref: https://en.wikipedia.org/wiki/Union_(set_theory)#Arbitrary_unions
description: The arbitary union operator acts on any iterable (of sets) M and returns a single set whose elements consist of the elements of each set in the iterable.
note: Throws an error if you don't give it exactly 1 argument
note: Throws an error if the input is not an iterable of sets
note: The above two notes will be referred to as (*), to avoid repetition below.

What you say: "The union of A and B" or "A union B"
What you type: A.union(B)
ref: https://en.wikipedia.org/wiki/Union_(set_theory)#Union_of_two_sets
description: The small union operator is a binary operator which takes in two sets.
note: (*)
note: the function should be able to take in an iterable of length 0 or 1.

  • Set.union([A]) should output A.
  • Set.union([]) should output the empty set.

better whitespace in docs

It's weird in the docs how the "example" section has an abnormally large amount of whitespace above it, and the title for a new function has almost no whitespace above it.

It makes it look like the "example" belongs to the function below it, when this is not the case.

Current doc image:

Screenshot 2019-04-13 22 42 33

As you can see "(static) complement..." has almost no whitespace above it, but it should have a large amount of whitespace.

I want to play around with the CSS file a bit and make the docs more readable.

Split into modules as file will soon exceed 1000 lines

It makes sense to split the code into seperate files (aka modules). However, we need first to complete the the missing enhancements and then analyze the code structure to determine, where it makes sense to move code into own files and where not.

Update README

Add the description about testing in the README:

You can run the tests like the following:

$ cd js-set-extension/package
$ npm install

To run tests in watch mode use

$ npm run test-watch

or for a single run use

$ npm run test

The tests are written in mocha but it should not be that hard to get into it as it is written very intuitive.

Linting

Please note, that the tests are very strict about code style and you can check for code style related errors using

npm run lint

You should fix these lint errors, since the CI server will reject to run any tests when the linter as thrown an error.

You can also run lint and tests all in one process using

npm run lint-test

The scripts to run these commands are also in the package.json file:

https://github.com/jankapunkt/js-set-extension/blob/master/package/package.json

How to update the code to this PR

If you make updates to your forked repo on the branch you have opened this PR (it is MareoRaft:master as you can see in the title) it will automatically be added to this PR and the CI server will also run the tests again. So no worries in changing and updating your code here.

Containment

There needs to be a boolean operation on instances of Sets that allow the following:

What you say: "if A is a proper superset of B, ..."
What you type: if (A.isProperSuperset(B)) {
note: After some nail biting, I settled on the word 'of' being builtin to functions. We say "f of x" and we write "f(x)". We don't write the of, but instead it is as-if the open-parenthesis is the of.

What you say: "if A is a proper subset of B, ..."
What you type: if (A.isProperSubset(B)) {

Request for set difference method

Is your feature request related to a problem? Please describe.
It seems that the builtin ES6 Set class has no set subtraction.

Describe the solution you'd like
Add a diff method to the set class. (I see you have a symDiff already, but no diff)

Describe alternatives you've considered
It would either...

  • take in a single argument and perform the set difference. For example, A.diff(B) returns A \ B
  • or take in a list of arguments and subtract all of them from the original set. A.diff([B, C]) returns (A \ B) \ C or A \ (B โˆช C).

Additional context
I can make a PR request for this if you'd like. Part of this is just me trying to see if you are active on GitHub or not.

more meta tags so people can find repo

Is it possible to add more meta tags to the GitHub repo? Currently we have

  • javascript
  • set
  • set-theory
  • math

I think we should also add

  • union
  • intersection
  • difference
  • subset

and even more, if GitHub allows it.

As for the NPM listing, currently we have

  • set
  • math
  • superset
  • subset
  • union
  • intersection
  • complement
  • symmetric difference
  • powerset

to which we could add

  • difference
  • set theory
  • proper subset
  • proper superset

. The reason behind all of this is simply to help people to find our repo when they are searching for it. I'm hoping we can increase visibility of this repo and ultimately get more people to use it.

Equality

There needs to be a boolean operation on instances of Sets that allow the following:

What you say: "if A is equal to B, ..." or "if A equals B, ..."
What you type: if (A.equals(B)) {

Update CI Environment

We can't merge, because the Node environment fails on our CI. Needs top be fixed soon!

// cc @MareoRaft sorry for the longer break, I will check on that soon and then we can continue to merge and improve to v2

create randomElement method

create randomElement boolean method for Set

Returns an element from the set, at random, with a uniform distribution.

something like

() => Math.floor(Math.random() *  this.size)

differences

There needs to be a boolean operation on instances of Sets that allow the following:

What you say: "The set difference of A and B"
What you type: Set.difference(A, B)
note: no change

What you say: "A minus B"
What you type: A.minus(B)
description: This is the same as the difference operator, but with a different syntax.

What you say: "The symmetric difference of M"
What you type: Set.symmetricDifference(M)
ref: https://en.wikipedia.org/wiki/Symmetric_difference#n-ary_symmetric_difference
description: The repeated symmetric difference, as described in ref above.
note: This function should be able to take in an iterable of length 0 or 1.

  • Set.symmetricDifference([A]) should output A.
  • Set.symmetricDifference([]) should output the empty set.

What you say: "The symmetric difference of A and B"
What you type: A.symmetricDifference(B)
ref: https://en.wikipedia.org/wiki/Symmetric_difference
description: A triangle B.

products

There needs to be a boolean operation on instances of Sets that allow the following:

What you say: "The cartesian product of M"
What you type: Set.cartesianProduct(M)
description: Perform the n-ary cartesian product (aka the n-fold cartesian product) of all the sets in X
example:

  • Set.cartesianProduct([A, B, C]) should output the set whose elements anything of the form (a, b, c) where a is in A, b is in B, and c is in C.
    note: Note that A.cartesianProduct(B).cartesianProduct(C) is NOT the same as Set.cartesianProduct([A, B, C]).

What you say: "The cartesian product of A and B"
What you type: A.cartesianProduct(B)
ref: https://en.wikipedia.org/wiki/Cartesian_product
description: the binary operation version.

Suggested properties

Looking through http://doc.sagemath.org/html/en/reference/sets/sage/sets/set.html, I think we might consider a few additional properties/methods, and maybe a few changes:

  • anElement --> might choose this name over any (my only worry about "any" is that I expect it to be a function that takes in a boolean function and returns true if the boolean function evaluates to true on any of the elements in the set)

  • isEmpty --> tells you if it's an empty set or not (has a size of 0)

  • cardinality --> doesn't really make sense to have this unless we supported infinite sets. (returns the size or "Infinity")

  • isFinite --> doesn't really make sense to have this unless we support infinite sets. (returns true or false)

  • subsets --> we might choose this name over powerSet, if you are leaning towards following Sagemath naming conventions as much as possible

  • randomElement --> returns an element of the set at random. (uses Math.random internally)

I think we could move forward with isEmpty now. We can move forward with randomElement if you agree with the name choice. Change of name for anElement and subsets is really up to your opinion and what convention we agree on for the naming scheme. The final two cardinality and isFinite arguably shouldn't exist since we don't support infinite sets right now.

Once we are in agreement for any one of these, we can open up a separate issue for it.

isEmpty method

Create an isEmpty boolean method for Set.

isEmpty --> tells you if it's an empty set or not (has a size of 0)

A.isEmpty()

something like

() => this.size === 0

power set

There needs to be a boolean operation on instances of Sets that allow the following:

What you say: "The power set of A" or "The set of subsets of A"
What you type: Set.powerSet(A)
note: I have always heard people always say "the power set of A", but never "the power of A". Hence, I believe truncating the function name to only "power" would cause confusion, since the term "power" can mean so many different things.

Why can we use global variable?

I am writing a similar extension and I found this project. It's an awesome project. But I can't figure out why can use global variable directly?

Maybe the purpose is that package can be used in browser and nodejs.

But why and what make it works. Is it babel or core.js? Can you share some info about that?

Thank you:)

Power sets are broken for ES6

Describe the bug
The power set function is broken in ES6 (at least, as transformed via Babel).

To Reproduce

$ cat .babelrc
{
  "presets": ["@babel/preset-env"]
}
$ babel-node
babel > require('set-extensions');
{}
babel > Set.power(new Set([1,2,3]));
Set(8) {
  Set(1) { 3 },
  Set(2) { 3, 2 },
  Set(2) { 3, 1 },
  Set(3) { 3, 2, 1 },
  Set(0) {},
  Set(1) { 1 },
  Set(1) { 2 },
  Set(1) { 3 }
}

Expected behavior
The set {2, 1} should be included in the power set.

Desktop (please complete the following information):

  • OS: macOS Catalina 10.15.6
  • Browser: node.js
  • Version: v14.8.0

Additional context

  • babel-node version: 7.8.4
  • set-extensions version: 1.4.1
  • @babel/core version: 7.11.6
  • @babel/preset-env version: 7.11.5

Code coverage broken?

Running the tests with coverage always results in 0% and I can't seem to find the reason.

suggested function list

i'm going to explain this soon, but i need to jot something down real quick. you can ignore this for now

list in progress

isProperSubset --> isStrictSubset, properSubset, strictSubset

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.