npm package: @sugarcoated/fondant-collection
Description: Collection, better Map.
Author: Joshua Crowe, Junior Web Developer
Latest version: 1.1.1

# About Collection
`Collection` extends `Map` to provide `Array`'s methods, along with caching to reduce the cost of accession. If you would like to read more spexific documentation about `Collection`, you can head to the [GitHub Wiki](https://github.com/Sugarcoated/Fondant/wiki/Collection).

# API Reference

### `new Collection([iterable])`
Creates a new `Collection` instance.

* `iterable` is an optional parameter, expected as an `Array.<Array.<String, Object>>` (Key Value Pairs), representing an initial set of values to add to the `Collection`. 

      new Collection();
      new Collection([['one', 1], ['two', 2], ['three', 3]])

In the first example, a `Collection` is instantiated without any initialiser, the second with an initialiser of three unique Key Value Pairs.

This mostly works identically to `Map#constructor`, which can be read about [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map). `Collection`'s constructor adds a few private properties for the caching `Array`s.

Upon construction, you will have access to the following properties:

* `items` is the cache for all Key Value Pairs.
* `keys` is the cache for all Keys from the Key Value Pairs.
* `values` is the cache for all Values from the Key Value Pairs.

### `.set(name, value)`
Overrides `Map`'s method (which can be read about [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set)) to reset item caches.

* `name` is expected as a `String`, identifying the name/key that will identify the particular pair.
* `value` is expected as an `Object`, and can contain any `Object`.

      const myCollection = new Collection();
      
      myCollection.set('one', 1);

### `.delete(name)`
Overrides `Map`'s method (which can be read about [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete)) to reset item caches.

* `name` is expected as a `String`, identifying the nae/key within the `Collection` to remove.

      const myCollection = new Collection([['one', 1]]);

      myCollection.delete('one');

### `.index([number])`
Access an item at a particular index. Exposes index accession by proxying bracket notation on the values cache.

* `number` is an optional paramter, expected as a `Number`, representing the index to access. When no `number` is specified, the first element (`[0]`) is accessed.

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.index(1); // ['two', 2]

### `.first()`
Accesses the first item within the `Collection`, similar to the default behavior of `.index()`.

* _Does not accept any arguments._

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.first(); // ['one', 1]

### `.last()`
Accesses the last item within the `Collection`.

* _Does not accept any arguments._

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.last(); // ['three', 3]

### `.find(prop, [value])`
Searches a `Collection` for an item that meets the conditioned passed as `prop`. This method is to be used when you do not know the key an `Object` is indexed under.

* `prop` is expected as either a `String` or a `Function`, expressing a condition for the item to meet.

      const myCollection = new Collection([
        ['Player 1', {name: 'Tom', age: 17}],
        ['Player 2', {name: 'Sam', age: 19}],
        ['Player 3', {name: 'Jack', age: 24}]
      ]);

      myCollection.find('name', 'Sam'); // {name: 'Sam', age: 19}
      myCollection.find((x, y) => y.age > 19); // {name: 'Jack', age: 24}

In the first example, the user `Sam` is being queried by the `name` property on the object indexed under the key `Player 2`; the second is finding any user who's age is above `19`, only returning the object for `Jack`.

### `.filter(condition, [binding])`
Filters the `Collection` into a new `Collection` containing only the items meeting the `condition` passed.

* `condition` is expected as a `Function`, expressing an evaluation that will result in a `Boolean`.
* `binding` is an optional parameter, expected as an `Object` to bind to the `condition`, setting the `this` value.

      const myCollection = new Collection([
        ['Player 1', {name: 'Tom', age: 17}],
        ['Player 2', {name: 'Sam', age: 19}],
        ['Player 3', {name: 'Jack', age: 24}]
      ]);

      myCollection.filter(x => x.age > 17); // [Player 2, Player 3]

In this example, we are filtering for all players that are older than `17`, returning an `Array.<Object>` containing the objects indexed under `Player 2` and `Player 3`.

### `.map(condition, [binding])`
Maps the `Collection` into a new `Collection` containing only the items returned during the `condition` called for each item.

* `condition` is expected as a `Function`, expressing an evaluation for each item to be mapped.
* `binding` is an optional parameter, expected as an `Object` to bind to the `condition`, setting the `this` value.

      const myCollection = new Collection([
        ['Player 1', {name: 'Tom', age: 17}],
        ['Player 2', {name: 'Sam', age: 19}],
        ['Player 3', {name: 'Jack', age: 24}]
      ]);

      myCollection.map(x => a.age = 10); // every player's age is 10 in the new Collection

### `.some(condition, [binding])`
Evaluates the `Collection` for a single item that meets the `condition`.

* `condition` is expected as a `Function`, expressing an evaluation that will result in a `Boolean`.
* `binding` is an optional parameter, expected as an `Object` to bind to the `condition`, setting the `this` value.

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.some(X => x > 2); // true

### `.every(condition, binding)`
Evaluates the `Collection` for all items meeting a `condition`.

* `condition` is expected as a `Function`, expressing an evaluation that will result in a `Boolean`.
* `binding` is an optional parameter, expected as an `Object` to bind to the `condition`, setting the `this` value.

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.some(x => (x > 0 && x < 4)); // true

### `.reduce(condition, initial)`
Reduces a `Collection` by an accumulator.

* `condition` is expected as a `Function`, expressing an evaluation that will result in a reduction of two items.
* `binding` is an optional parameter, expected as an `Object` to bind to the `condition`, setting the `this` value.

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.reduce((x, y) => x + y); // 6

### `.clone()`
Creates an identical copy of the `Collection` called on.

* _Does not accept any arguments._

      const myCollection = new Collection([['one', 1], ['two', 2], ['three', 3]]);

      myCollection.clone(); // Collection w/ one, two, three

### `.concat(concatenation)`
Concatenates multiple `Collection`s into a single `Collection`.

* `concatenation` is expected as either a `Collection` or an `Array.<Collection>`. This argument is spread regardless and looped through, so it is `Array` insensitive.

      const myCollection = new Collection([['one', 1]]);
      const myOtherCollection = new Collection([['two', 2]]);

      myCollection.concat(myOtherCollection); // Collection w/ one & two

### `.equals(reference)`
Evaluate one `Collection` to another.

* `reference` is expected as a `Collection`, typically as an `Object` reference.

      const myCollection = new Collection([['one', 1]]);
      const myOtherCollection = new Collection([['one', 1]]);

      myCollection.equals(myOtherCollection); // true