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 function eq(isEqual) and contains(includes) #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ npm install bue
## Usage

```javascript
var biu = require('bue');
var bue = require('bue');

bue.isArray([1,2,3]);
// => true
Expand All @@ -33,6 +33,11 @@ All the functions used in Bue is based on lodash(v4.0.0-pre), some of them have
```
bue.clone(value)
```
- eq
Compare two values(arrays, booleans, Date objects, numbers) if they ware equivalent.
```
bue.eq(object, other);
```
- isArray
Checks if `value` is classified as an `Array` object.
```
Expand Down Expand Up @@ -198,6 +203,11 @@ All the functions used in Bue is based on lodash(v4.0.0-pre), some of them have
### Collection Functions
> `bue.iteratee`: a function that a invokes `func` with the arguments of the created function.

- contains
Check if `target` is in `collection`
```
bue.contains(collection, value, [fromIndex=0])
```
- each
Iterates over elements of `collection` invoking `iteratee` for each element. The iteratee is invoked with three arguments: (value, index|key, collection). Iteratee functions may exit iteration early by explicitly returning `false`.
```
Expand Down
57 changes: 57 additions & 0 deletions lib/collection/includes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
var baseIndexOf = require('../internal/baseIndexOf'),
getLength = require('../internal/getLength'),
isArray = require('../lang/isArray'),
isIterateeCall = require('../internal/isIterateeCall'),
isLength = require('../internal/isLength'),
isString = require('../lang/isString'),
values = require('../object/values');

/* Native method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
* Checks if `target` is in `collection` using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons. If `fromIndex` is negative, it's used as the offset
* from the end of `collection`.
*
* @static
* @memberOf bue
* @alias contains, include
* @category Collection
* @param {Array|Object|string} collection The collection to search.
* @param {*} target The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @param- {Object} [guard] Enables use as a callback for functions like `bue.reduce`.
* @returns {boolean} Returns `true` if a matching element is found, else `false`.
* @example
*
* bue.includes([1, 2, 3], 1);
* // => true
*
* bue.includes([1, 2, 3], 1, 2);
* // => false
*
* bue.includes({ 'user': 'fred', 'age': 40 }, 'fred');
* // => true
*
* bue.includes('pebbles', 'eb');
* // => true
*/
function includes(collection, target, fromIndex, guard) {
var length = collection ? getLength(collection) : 0;
if (!isLength(length)) {
collection = values(collection);
length = collection.length;
}
if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
fromIndex = 0;
} else {
fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
}
return (typeof collection == 'string' || !isArray(collection) && isString(collection))
? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)
: (!!length && baseIndexOf(collection, target, fromIndex) > -1);
}

module.exports = includes;
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
// Language Functions
'clone': require('./lang/clone'),
'eq': require('./lang/isEqual'),
'isArray': require('./lang/isArray'),
'isBoolean': require('./lang/isBoolean'),
'isDate': require('./lang/isDate'),
Expand Down Expand Up @@ -40,6 +41,7 @@ module.exports = {
'escapeRegExp': require('./string/escapeRegExp'),

// Collection Functions
'contains': require('./collection/includes'),
'each': require('./collection/forEach'),
'eachRight': require('./collection/forEachRight'),
'map': require('./collection/map'),
Expand Down
27 changes: 27 additions & 0 deletions lib/internal/baseIndexOf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var indexOfNaN = require('./indexOfNaN');

/**
* The base implementation of `bue.indexOf` without support for binary searches.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
if (value !== value) {
return indexOfNaN(array, fromIndex);
}
var index = fromIndex - 1,
length = array.length;

while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}

module.exports = baseIndexOf;
39 changes: 39 additions & 0 deletions lib/internal/bindCallback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var identity = require('../utility/identity');

/**
* A specialized version of `baseCallback` which only supports `this` binding
* and specifying the number of arguments to provide to `func`.
*
* @private
* @param {Function} func The function to bind.
* @param {*} thisArg The `this` binding of `func`.
* @param {number} [argCount] The number of arguments to provide to `func`.
* @returns {Function} Returns the callback.
*/
function bindCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
return identity;
}
if (thisArg === undefined) {
return func;
}
switch (argCount) {
case 1: return function(value) {
return func.call(thisArg, value);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
case 5: return function(value, other, key, object, source) {
return func.call(thisArg, value, other, key, object, source);
};
}
return function() {
return func.apply(thisArg, arguments);
};
}

module.exports = bindCallback;
23 changes: 23 additions & 0 deletions lib/internal/indexOfNaN.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Gets the index at which the first occurrence of `NaN` is found in `array`.
*
* @private
* @param {Array} array The array to search.
* @param {number} fromIndex The index to search from.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {number} Returns the index of the matched `NaN`, else `-1`.
*/
function indexOfNaN(array, fromIndex, fromRight) {
var length = array.length,
index = fromIndex + (fromRight ? 0 : -1);

while ((fromRight ? index-- : ++index < length)) {
var other = array[index];
if (other !== other) {
return index;
}
}
return -1;
}

module.exports = indexOfNaN;
20 changes: 20 additions & 0 deletions lib/internal/isLength.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
* of an array-like value.
*/
var MAX_SAFE_INTEGER = 9007199254740991;

/**
* Checks if `value` is a valid array-like length.
*
* **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
*/
function isLength(value) {
return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

module.exports = isLength;
54 changes: 54 additions & 0 deletions lib/lang/isEqual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
var baseIsEqual = require('../internal/baseIsEqual'),
bindCallback = require('../internal/bindCallback');

/**
* Performs a deep comparison between two values to determine if they are
* equivalent. If `customizer` is provided it's invoked to compare values.
* If `customizer` returns `undefined` comparisons are handled by the method
* instead. The `customizer` is bound to `thisArg` and invoked with up to
* three arguments: (value, other [, index|key]).
*
* **Note:** This method supports comparing arrays, booleans, `Date` objects,
* numbers, `Object` objects, regexes, and strings. Objects are compared by
* their own, not inherited, enumerable properties. Functions and DOM nodes
* are **not** supported. Provide a customizer function to extend support
* for comparing other values.
*
* @static
* @memberOf bue
* @alias eq
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize value comparisons.
* @param {*} [thisArg] The `this` binding of `customizer`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'user': 'fred' };
* var other = { 'user': 'fred' };
*
* object == other;
* // => false
*
* bue.isEqual(object, other);
* // => true
*
* // using a customizer callback
* var array = ['hello', 'goodbye'];
* var other = ['hi', 'goodbye'];
*
* bue.isEqual(array, other, function(value, other) {
* if (bue.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {
* return true;
* }
* });
* // => true
*/
function isEqual(value, other, customizer, thisArg) {
customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
var result = customizer ? customizer(value, other) : undefined;
return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
}

module.exports = isEqual;
11 changes: 10 additions & 1 deletion test/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@ describe ('Collection', function() {

beforeEach(function() {
iterator = 0;
})
});

describe('#contains(collection, value)', function() {
it('Returns true if the equivalent values found', function() {
expect(bue.contains([1, 2, 3], 1)).to.equal(true);
expect(bue.contains([1, 2, 3], 1, 2)).to.equal(false);
expect(bue.contains({ 'user': 'fred', 'age': 40 }, 'fred')).to.equal(true);
expect(bue.contains('pebbles', 'eb')).to.equal(true);
});
});

describe('#each(collection)', function() {
it('should return each element key & value', function() {
Expand Down
10 changes: 10 additions & 0 deletions test/language.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ describe ('Language', function() {
});
});

describe('#eq(object, target)', function() {
var object = { 'user': 'fred' };
var other = { 'user': 'fred' };

it('Returns true if the values are equivalent', function() {
expect(bue.eq(object, other)).to.equal(true);
expect(object === other).to.equal(false);
});
});

describe('#isArray(value)', function() {
it('should return if `value` is classified as an `Array` object', function() {
expect(bue.isArray('abc')).to.equal(false);
Expand Down