Comparing version 1.7.2 to 1.8.0
@@ -48,3 +48,3 @@ 'use strict'; | ||
if (_.isArray(obj)) { | ||
if (value === undefined && !(value in obj)) { | ||
if (value === undefined && !(key in obj)) { | ||
//empty slot | ||
@@ -208,10 +208,12 @@ return; | ||
} | ||
// if (!_.exists) { | ||
// _.mixin({ | ||
// exists: function(obj, path) { | ||
// console.log(this); | ||
// return _.hasIn(obj, path); | ||
// }, | ||
// }); | ||
// } | ||
if (!_.exists) { | ||
_.mixin({ | ||
exists: function(obj, path) { | ||
path = _.isArray(path) ? _.clone(path) : _.toPath(path); | ||
var key = path.pop(); | ||
var parent = path.length ? _.get(obj, path) : obj; | ||
return parent !== undefined && key in parent; | ||
}, | ||
}); | ||
} | ||
if (!_.condense) { | ||
@@ -218,0 +220,0 @@ _.mixin({ |
{ | ||
"name": "deepdash", | ||
"version": "1.7.2", | ||
"version": "1.8.0", | ||
"description": "Object tree traversal for lodash", | ||
@@ -5,0 +5,0 @@ "main": "deepdash.js", |
274
README.md
<img src="deepdash.svg?sanitize=true" width="64px"/> | ||
## Deepdash | ||
Looking for eachDeep, filterDeep, keysDeep etc? Tree traversal extension for lodash. | ||
Looking for eachDeep, filterDeep, keysDeep etc? Tree traversal extension for Lodash. | ||
@@ -10,3 +10,3 @@ [![npm](https://img.shields.io/npm/v/deepdash.svg)](https://www.npmjs.com/package/deepdash) [![Travis (.org)](https://api.travis-ci.org/YuriGor/deepdash.svg?branch=master)](https://travis-ci.org/YuriGor/deepdash) [![Coverage Status](https://coveralls.io/repos/github/YuriGor/deepdash/badge.svg?branch=master)](https://coveralls.io/github/YuriGor/deepdash?branch=master) <br> | ||
### Installation | ||
In a browser load [script](https://raw.githubusercontent.com/YuriGor/deepdash/master/deepdash.js) after lodash: | ||
In a browser load [script](https://raw.githubusercontent.com/YuriGor/deepdash/master/deepdash.js) after Lodash: | ||
```html | ||
@@ -22,3 +22,3 @@ <script src="lodash.js"></script> | ||
```js | ||
//mixin new methods into lodash object | ||
//mixin new methods into Lodash object | ||
const _ = require('deepdash')(require('lodash')); | ||
@@ -115,2 +115,63 @@ ``` | ||
- [condense](#condense) - condense sparse array | ||
- [condenseDeep](#condensedeep) - condense all the nested arrays | ||
- [eachDeep](#eachdeep-foreachdeep) - (forEachDeep) iterate over all the children and sub-children | ||
- [exists](#exists) - like a `_.has` but returns `false` for empty array slots | ||
- [filterDeep](#filterdeep) - deep filter object | ||
- [indexate](#indexate) - get an object with all the paths as keys and corresponding values | ||
- [paths](#paths-keysdeep) - (keysDeep) get an array of paths | ||
- [pathToString](#pathtostring) - convert an array to string path (opposite to _.toPath) | ||
### condense | ||
Makes sparse array non-sparse. This method mutates object. | ||
```js | ||
_.condense( | ||
arr // array to condense | ||
); | ||
``` | ||
**Example:** | ||
```js | ||
let arr = ['a', 'b', 'c', 'd', 'e']; | ||
delete arr[1]; | ||
console.log(arr); | ||
delete arr[3]; | ||
console.log(arr); | ||
_.condense(arr); | ||
console.log(arr); | ||
``` | ||
Console: | ||
``` | ||
[ 'a', <1 empty item>, 'c', 'd', 'e' ] | ||
[ 'a', <1 empty item>, 'c', <1 empty item>, 'e' ] | ||
[ 'a', 'c', 'e' ] | ||
``` | ||
### condenseDeep | ||
Make all the arrays in the object non-sparse. | ||
```js | ||
_.condenseDeep( | ||
obj, // The object to iterate over. | ||
options = { | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
} | ||
); | ||
``` | ||
**Example:** | ||
```js | ||
let obj = { arr: ['a', 'b', { c: [1, , 2, , 3] }, 'd', 'e'] }; | ||
delete obj.arr[1]; | ||
delete obj.arr[3]; | ||
_.condenseDeep(obj); | ||
console.log(obj); | ||
``` | ||
Console: | ||
``` | ||
{ arr: [ 'a', { c: [ 1, 2, 3 ] }, 'e' ] } | ||
``` | ||
### eachDeep (forEachDeep) | ||
@@ -155,17 +216,11 @@ | ||
``` | ||
### exists | ||
### indexate | ||
Check if path exists in the object considering sparse arrays. | ||
Alternative for Lodash `has` method, which returns true for empty array slots. | ||
Creates an 'index' flat object with paths as keys and corresponding values. | ||
```js | ||
_.indexate( | ||
obj, // The object to iterate over. | ||
options={ | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
includeCircularPath: true, /* If found some circular reference - include path to it into result or skip it. | ||
Option ignored if `checkCircular:false`. */ | ||
leafsOnly: true /* Return paths to childless values only by default. | ||
Or all the paths will be returned, including parents, if set to false. */ | ||
} | ||
_.exists( | ||
obj, // object to inspect | ||
path, // path(string|array) to check for existense | ||
) | ||
@@ -176,78 +231,9 @@ ``` | ||
```js | ||
let index = _.indexate( | ||
{ | ||
a: { | ||
b: { | ||
c: [1, 2, 3], | ||
'hello world': {}, | ||
}, | ||
}, | ||
}, | ||
{ leafsOnly: true } | ||
); | ||
console.log(index); | ||
var obj = [,{a:[,'b']}]; | ||
_.exists(obj, 0); // false | ||
_.exists(obj, 1); // true | ||
_.exists(obj, '[1].a[0]'); // false | ||
_.exists(obj, '[1].a[1]'); // true | ||
``` | ||
Console: | ||
``` | ||
{ 'a.b.c[0]': 1, | ||
'a.b.c[1]': 2, | ||
'a.b.c[2]': 3, | ||
'a.b["hello world"]': {} } | ||
``` | ||
### paths (keysDeep) | ||
Creates an array of the paths of object or array. | ||
```js | ||
_.paths( | ||
obj, // The object to iterate over. | ||
options = { | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
includeCircularPath: true, /* If found some circular reference - include path to it into result or skip it. | ||
Option ignored if `checkCircular:false`. */ | ||
leafsOnly: true /* Return paths to childless values only by default. | ||
Or all the paths will be returned, including parents, if set to false. */ | ||
} | ||
) | ||
``` | ||
**Example:** | ||
```js | ||
let paths = _.paths({ | ||
a: { | ||
b: { | ||
c: [1, 2, 3], | ||
"hello world":{} | ||
}, | ||
}, | ||
},{ leafsOnly: false }); | ||
console.log(paths); | ||
paths = _.paths({ | ||
a: { | ||
b: { | ||
c: [1, 2, 3], | ||
"hello world":{} | ||
}, | ||
}, | ||
}); | ||
console.log(paths); | ||
``` | ||
Console: | ||
``` | ||
[ 'a', | ||
'a.b', | ||
'a.b.c', | ||
'a.b.c[0]', | ||
'a.b.c[1]', | ||
'a.b.c[2]', | ||
'a.b["hello world"]' ] | ||
[ | ||
'a.b.c[0]', | ||
'a.b.c[1]', | ||
'a.b.c[2]', | ||
'a.b["hello world"]' ] | ||
``` | ||
### filterDeep | ||
@@ -262,5 +248,5 @@ | ||
(value, key|index, path, depth, parent, parentKey, parentPath, parents) | ||
- If predicate returns `true` - value will be deeply cloned to result object | ||
- If predicate returns `true` - value will be deeply cloned to the result object, | ||
no further iteration over children of this value will be performed. | ||
- If predicate returns `false` - value will be completely excluded from the result object | ||
- If predicate returns `false` - value will be completely excluded from the result object, | ||
no further iteration over children of this value will be performed. | ||
@@ -271,8 +257,8 @@ - If predicate returns `undefined` - current path will only appear in the result object | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
keepCircular: true, // result object will contain circular references if they passed the filter. | ||
keepCircular: true, // The result object will contain circular references if they passed the filter. | ||
// replaceCircularBy: <value>, // Specify the value to replace circular references by. | ||
leafsOnly: true, /* Call predicate for childless values only by default. | ||
Or all the intermediate objects will be passed into predicate, including parents, if set to false. */ | ||
condense: true, // Condense result object, since exluding some paths may produce sparse arrays | ||
cloneDeep: _.cloneDeep, // Method to use for deep cloning values, lodash cloneDeep by default. | ||
Or, if set to false, all the intermediate objects will be passed into the predicate, including parents. */ | ||
condense: true, // Condense the result object, since excluding some paths may produce sparse arrays | ||
cloneDeep: _.cloneDeep, // Method to use for deep cloning values, Lodash cloneDeep by default. | ||
pathFormat: 'string', /* 'string'|'array' - specifies the format of paths passed to the iteratee. | ||
@@ -324,10 +310,17 @@ 'array' is better for performance.*/ | ||
### condense | ||
### indexate | ||
Makes sparse aray non-sparse. This method mutates object. | ||
Creates an 'index' flat object with paths as keys and corresponding values. | ||
```js | ||
_.condense( | ||
arr // array to condense | ||
); | ||
_.indexate( | ||
obj, // The object to iterate over. | ||
options={ | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
includeCircularPath: true, /* If found some circular reference - include a path to it into the result or skip it. | ||
Option ignored if `checkCircular:false`. */ | ||
leafsOnly: true /* Return paths to childless values only by default. | ||
Or all the paths will be returned, including parents, if set to false. */ | ||
} | ||
) | ||
``` | ||
@@ -337,42 +330,77 @@ | ||
```js | ||
let arr = ['a', 'b', 'c', 'd', 'e']; | ||
delete arr[1]; | ||
console.log(arr); | ||
delete arr[3]; | ||
console.log(arr); | ||
_.condense(arr); | ||
console.log(arr); | ||
let index = _.indexate( | ||
{ | ||
a: { | ||
b: { | ||
c: [1, 2, 3], | ||
'hello world': {}, | ||
}, | ||
}, | ||
}, | ||
{ leafsOnly: true } | ||
); | ||
console.log(index); | ||
``` | ||
Console: | ||
``` | ||
[ 'a', <1 empty item>, 'c', 'd', 'e' ] | ||
[ 'a', <1 empty item>, 'c', <1 empty item>, 'e' ] | ||
[ 'a', 'c', 'e' ] | ||
{ 'a.b.c[0]': 1, | ||
'a.b.c[1]': 2, | ||
'a.b.c[2]': 3, | ||
'a.b["hello world"]': {} } | ||
``` | ||
### condenseDeep | ||
### paths (keysDeep) | ||
Make all the arrays in the object non-sparse. | ||
Creates an array of the paths of object or array. | ||
```js | ||
_.condenseDeep( | ||
obj, // The object to iterate over. | ||
_.paths( | ||
obj, // The object to iterate over. | ||
options = { | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
checkCircular: false, // Check each value to not be one of the parents, to avoid circular references. | ||
includeCircularPath: true, /* If found some circular reference - include a path to it into the result or skip it. | ||
Option ignored if `checkCircular:false`. */ | ||
leafsOnly: true /* Return paths to childless values only by default. | ||
Or all the paths will be returned, including parents, if set to false. */ | ||
} | ||
); | ||
) | ||
``` | ||
**Example:** | ||
```js | ||
let obj = { arr: ['a', 'b', { c: [1, , 2, , 3] }, 'd', 'e'] }; | ||
delete obj.arr[1]; | ||
delete obj.arr[3]; | ||
_.condenseDeep(obj); | ||
console.log(obj); | ||
let paths = _.paths({ | ||
a: { | ||
b: { | ||
c: [1, 2, 3], | ||
"hello world":{} | ||
}, | ||
}, | ||
},{ leafsOnly: false }); | ||
console.log(paths); | ||
paths = _.paths({ | ||
a: { | ||
b: { | ||
c: [1, 2, 3], | ||
"hello world":{} | ||
}, | ||
}, | ||
}); | ||
console.log(paths); | ||
``` | ||
Console: | ||
``` | ||
{ arr: [ 'a', { c: [ 1, 2, 3 ] }, 'e' ] } | ||
[ 'a', | ||
'a.b', | ||
'a.b.c', | ||
'a.b.c[0]', | ||
'a.b.c[1]', | ||
'a.b.c[2]', | ||
'a.b["hello world"]' ] | ||
[ | ||
'a.b.c[0]', | ||
'a.b.c[1]', | ||
'a.b.c[2]', | ||
'a.b["hello world"]' ] | ||
``` | ||
### pathToString | ||
@@ -379,0 +407,0 @@ |
@@ -160,2 +160,36 @@ 'use strict'; | ||
}); | ||
it('empty slots skipped', () => { | ||
var obj = [ | ||
, | ||
[, { a: 'b' }, , { c: 'd' }, [, 1, , 2, , 3]], | ||
, | ||
[, , , 'a'], | ||
{}, | ||
]; | ||
_.eachDeep(obj, (v) => { | ||
expect(v).not.to.equal(undefined); | ||
}); | ||
}); | ||
it('undefined are valid values, no skip', () => { | ||
var obj = [ | ||
, | ||
[ | ||
, | ||
{ a: undefined }, | ||
, | ||
{ c: undefined }, | ||
[, undefined, , undefined, , undefined], | ||
], | ||
, | ||
[, , , undefined], | ||
{}, | ||
]; | ||
let u = 0; | ||
_.eachDeep(obj, (v) => { | ||
if (v === undefined) { | ||
u++; | ||
} | ||
}); | ||
expect(u).to.equal(6); | ||
}); | ||
}); |
@@ -14,3 +14,2 @@ 'use strict'; | ||
it('slot 0', () => { | ||
return; | ||
var arr = [, 'b', , 'd', 'e']; | ||
@@ -30,3 +29,14 @@ expect(_.exists(arr, 0)).to.equal(false); | ||
expect(_.exists(arr, 4)).to.equal(true); | ||
arr = [arr]; | ||
expect(_.exists(arr, '[0][0]')).to.equal(false); | ||
expect(_.exists(arr, '[0][1]')).to.equal(true); | ||
expect(_.exists(arr, '[0][2]')).to.equal(false); | ||
expect(_.exists(arr, '[0][3]')).to.equal(true); | ||
expect(_.exists(arr, '[0][4]')).to.equal(true); | ||
expect(_.exists(arr, [0, 0])).to.equal(false); | ||
expect(_.exists(arr, [0, 1])).to.equal(true); | ||
expect(_.exists(arr, [0, 2])).to.equal(false); | ||
expect(_.exists(arr, [0, 3])).to.equal(true); | ||
expect(_.exists(arr, [0, 4])).to.equal(true); | ||
}); | ||
}); |
@@ -167,1 +167,11 @@ 'use strict'; | ||
}); | ||
describe('docs for exists', () => { | ||
it('exists', () => { | ||
var obj = [, { a: [, 'b'] }]; | ||
expect(_.exists(obj, 0)).to.equal(false); | ||
expect(_.exists(obj, 1)).to.equal(true); | ||
expect(_.exists(obj, '[1].a[0]')).to.equal(false); | ||
expect(_.exists(obj, '[1].a[1]')).to.equal(true); | ||
}); | ||
}); |
@@ -13,3 +13,3 @@ 'use strict'; | ||
describe('string paths', () => { | ||
it('[', () => { | ||
it('[.]\'"', () => { | ||
let o = { a: { '[': 'c', '"\'': 'd', '.': 'e' } }; | ||
@@ -16,0 +16,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
77321
2175
417