Code Monkey home page Code Monkey logo

lodash-deep's Introduction

lodash-deep

Lodash mixins for (deep) object accessing / manipulation.

Bower version NPM version Build Status Sauce Test Status Dependency Status

Version 2.x

In 2.0 most of the methods of this module where removed, because Lodash now supports their functionality natively. E.g.:

_.deepGet(object, 'father.name');
// ->
_.get(object, 'father.name');

_.deepPluck(array, 'father.name');
// ->
_.map(array, 'father.name');

Compatibility

lodash-deep is currently compatible with:

  • Node.js
  • All ES5 compatible browsers (IE9+, Chrome, Firefox, Safari etc)

Installation

Bower

  1. bower install lodash-deep
  2. Reference lodash-deep.min.js after lodash.min.js

Node.js

  1. npm install lodash
  2. npm install lodash-deep
  3. var _ = require("lodash");
    _.mixin(require("lodash-deep"));

Docs

The following mixins are included in lodash-deep:

_.deepMapValues(object, propertyPath)

Maps all values in an object tree and returns a new object with the same structure as the original.

object

Type: Object

The root object of the object tree.

callback

Type: Function

The function to be called per iteration on any non-object value in the tree.

Callback is invoked with 2 arguments: (value, path).

value the value of the current property.

path the path of the current property.

returns

Type: Object

var object = {
    level1: {
        value: 'value 1'
        level2: {
            value: 'value 2'
            level3: {
                value: 'value 3'
            }
        }
    }
};

_.deepMapValues(object, function(value, path){
    return path + ' is ' + value)
});

/** ->
 *    {
 *        level1: {
 *            value: 'level1.value is value 1'
 *            level2: {
 *                value: 'level1.level2.value is value 2'
 *                level3: {
 *                    value: 'level1.level2.level3.value is value 3'
 *                }
 *            }
 *        }
 *    };
 */

Contributing

Please use the canary branch when creating a pull request.

Contributors

lodash-deep's People

Contributors

andrewluetgers avatar beaugunderson avatar james1x0 avatar spenceralger avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lodash-deep's Issues

_.deepPluck on multi-level data.

Greetings, thank you for working so hard on this. Great stuff. :)

Is there any plans to add the functionality to _.deepPluck to find all of what you are looking for? Currently, you can only snipe all the values on a given object depth.

Unless I am missing something?

Also, below is my current workaround.

Thank you for your time.


Test Data
var testData = [
    { 
        type: "apple", 
        color: "green", 
        quantity: 1000,
        deeper: {
            type: "waffle",
            color: "brownish",
            quantity: 1000,
            moarDeeper: {
                type: "cake",
                color: "whiteish",
                quantity: 1000
            }
        }
  },
    { type: "apple", color: "red", quantity: 2000 },
    { type: "grape", color: "green", quantity: 1000 },
    { type: "grape", color: "red", quantity: 4000 }
];
Test Output
_.deepPluck(input,'color');
// => results
["green", "red", "green", "red"]

_.deepPluck(input,'nest.color');
// => results
["waffle", undefined, undefined, undefined]

Current Workaround
function pluckRecursive(input, prop, collect) {
    collect = collect || [];

    if (_.isArray(input)) {
        _.forEach(input, function (value, key) {
            pluckRecursive(value, prop, collect);
        })    
    } else if (_.isObject(input)) {
        _.forEach(input, function (value, key) {
            if (key === prop) {
                collect.push(value);
            } else {
                pluckRecursive(value, prop, collect);
            }
        })    
    }
    return collect;
};
Workaround Output
_.flatten(pluckRecursive(input, 'color'))
// => results
["green", "waffle", "foot", "red", "green", "red"]

getPropertyPathParts issue, unable to 'pull'

From what I can teel getPropertyPathParts doesn't seem to be breaking apart the path correctly when it is a string such as _.deepGet(post, 'user') or _.deepGet(post, 'user.name.first').

TypeError: Cannot read property 'pull' of undefined

From what I can tell the string is getting reversed to tsrif.eman.resu then passed through the regex. I find this a bit confusing, but I presume it is for a reason. I also noted that the .forEach step returns undefined which is probably the cause of 'pull' step failing.

Feature request: deepPick

Would this work?

function deepPick(object, paths) {
     var p, path, result = {};

     for (p in paths) {
         path = paths[p];

         _.set(result, path, _.get(object, path));
     }

     return result;                                                                                                                       
 }

deepMapValue not returning array, but string or number

In previous versions, this seems to have been working, however, having upgraded to 2.0, it seems that now it returns a number for a single depth object, and a string, delimited by periods, for deeper objects. The documentation says array as well.

Is this a non-documented change or is something not working correctly?

Using "_.deepPluck" callback shorthand

Many of lodash's methods allow usage of the _.pluck shorthand. In all of these cases, equivalent methods could be added here. Not sure how much value it truly adds, but maybe this can start the discussion.

Lodash example:

var characters = [
  { 'name': 'barney', 'age': 36 },
  { 'name': 'fred',   'age': 40 }
];

_.max(characters, function(chr) { return chr.age; });
// → { 'name': 'fred', 'age': 40 };

// using "_.pluck" callback shorthand
_.max(characters, 'age');
// → { 'name': 'fred', 'age': 40 };

Lodash Deep example:

var characters = [
  {
    personal: { name: 'fred', age: 40 },
    professional: { employer: 'slate rock and gravel company', title: 'geological engineer' }
  }, {
    personal: { name: 'barney', age: 36 },
    professional: { employer: 'redacted', title: 'top-secret' }
  }
];

// using "_.deepPluck" callback shorthand
_.deepMax(characters, 'personal.age');
/* →
  {
    personal: { name: 'fred', age: 40 },
    professional: { employer: 'slate rock and gravel company', title: 'geological engineer' }
  }
*/

Consider adding createArrays flag to _.deepSet

The current behavior of _.deepSet can cause problems in some border cases where

  • _.deepSet is used to create missing objects.
  • The missing objects have arrayKeys as key.

This can be solved by adding a createArrays parameter to _.deepSet, which defaults to true. Also the documentation currently does not have an example where missing arrays are created.

IE7, IE8 compatibility

Currently lodash-deep is not compatible with IE7 and IE8. The incomatibility issues should be identified and resolved.

Require.js issue

When I do include with require js I got
Uncaught ReferenceError: module is not defined
What do you think to change condition for node.js to
if(typeof exports !== 'undefined'){
or something else ?

Name tweak.

The name lodash.deep will prevent Lo-Dash from being able to use that in the future as a method name in npm as our methods are split into individual packages. Would naming this lodash-deep be doable?

possibility of supporting bracket notation?

Right now you can do stuff like _.deepHas(foo, 'bar.baz'); but would it be possible to support bracket notation as well as dot? e.g.

_.deepHas(foo, 'bar[0].baz'); // => foo.bar[0].baz
_.deepHas(foo, 'bar[\'baz\'].qux'); // => foo.bar['baz'].qux
_.deepHas(foo, '[0].bar.baz'); // => foo[0].bar.baz
_.deepHas(foo, '[\'bar\'].baz.qux'); // => foo['bar'].baz.qux

I imagine the easiest way to do this would be to have the keys you pass in be escaped, so devs could either do '["foo"]' or '[\'foo\']', depending on their coding style.

What do you think?

EDIT: The only thing that this doesn't catch easily would be passing variables into keys, e.g.

var baz = 'some-value-I-got-dynamically';
_.deepHas(foo, 'bar[baz]');

It's something that might be useful, but I don't think is necessary in the short term.

methods should accept callbacks

In particular, I would like to use _.deepSetValue(object, propertyPath, value), however I'd like to manipulate the value based on what's already there. So an example usage would look something like this:

var object = {
    level1: {
        value: 'value 1',
        level2: Object.create({
            level3: {
                value: '2014-06-05T17:26:49Z'
            }
        })
    }
};

_.deepSetValue(object, 'level1.level2.level3.value', function(value) {
   return moment(value);
});
// -> { level1: { level2: { level3: { value: Moment {...} }}}}

considering the api, perhaps this would make more sense as a new method.

_.deepSet(...) does not have the exact same behavior as _.set(...)

There is slight difference between lodash-deep _.deepSet(...) and lodash _.set(...).

With lodash _.set if an object property that you wish to set in the future is a string or number and then try to set it with an assumption that it is an object with properties it will silently err and not actually set the value. _.deepSet however will ignore the type of the originally initialized value and will set it with whatever you set (i.e. change the original value to an object with its associated properties).

Example:

/*
    _.set(...) === _.deepSet(...) if setting same type (i.e. Number -> Number)
*/
var obj = { 'a': [{ 'b': { 'c': 3 } }] };
console.log(obj.a[0].b.c) // prints out 3

// _.set(...) === _.deepSet(...) 
// in this case
_.set(obj, 'a[0].b.c', 4000); 
console.log(obj.a[0].b.c) // prints out 4000


/*
   _.set(...) !== _.deepSet(...) if setting different type (i.e. String -> Object)
*/
var obj = { 'a': [{ 'b': { 'c': '' } }] };
console.log(obj.a[0].b.c) // prints out empty string

// _.set(...) !== _.deepSet(...)
// in this case
// here we are treating 'c' as an object with a property
_.set(obj, _.set(obj, 'a[0].b.c.someProp', 4000); 
console.log(obj.a[0].b.c) // still prints out empty string

// however _.deepSet(...) will set fine
_.deepSet(obj, _.set(obj, 'a[0].b.c.someProp', 4000); 
console.log(obj.a[0].b.c) // prints out an Object { someProp: 4000 }

This isn't so much a bug, as much as an instance where the two are not exactly the same so it might be worth noting in the documentation somewhere. I'm open to creating a PR to modify the docs or if the main contribs for lodash-deep wish to increase parity between the two then I don't mind creating a PR for that as well.

screen shot 2015-12-14 at 2 00 56 pm

New method: _.deepKeys

There're certainly situations where I could use this method:

var src = {
  "a": true,
  "b": {
    "ba": true,
    "bb": true
  }
}
var arr = _.deepKeys(src);
// returns ["a", "b.ba", "b.bb"]

This is my quick implementation which I needed:

function deepKeys(obj, path) {
  path = path || [];
  if (_.isArray(obj)) {
    path.push('0');
    obj = obj[0];
  }  
  return _.reduce(obj, function (result, value, key) {
    if (_.isPlainObject(value) || _.isArray(value)) {
      return result.concat(deepKeys(value, path.concat(key)));
    }
    result.push(path.concat(key).join("."));
    return result;
  }, []);
}

New Method: _.deepIndexBy, _.deepGroupBy

Thanks for awesome project.
I have found some lack of functionality which is deepIndexBy, deepGroupBy.

It'll be look like

var members = [{profile: {name: 'a', age: 11, sex: 'male'}, etc: {}}, {profile: {name: 'b', age: 100, sex: 'female'}, etc:{}};
_.deepGroupBy(members, 'profile.sex');

Use `_.runInContext`

Using _.mixin on the lodash Node package has the possibility of causing a conflict with other dependencies which may use it. Depending on how their dep version ranges are set up they may end up sharing the lodash package. To avoid extending the lodash package directly with _.mixin you could do:

_ = require('lodash').runInContext();

// later...
_.mixin(mixins);

// then...
module.exports = _;

Using _.runInContext creates a completely separate lodash function that can be extended w/o worrying about conflicts.

Don't treat integer property name as an array in _deepSet

Using integers as an property name in a object is valid but not possible now. An integer property will create a array.

var test;
var testStatus = {
  status: {
    someProperty: undefined,
    1: {
      name: undefined
    },
    2: {
      name: undefind
    }
  }
};

test = {};
_.deepSet(test, "status.1.name", "This is currently not working like expected.");

The default behavior of the dot notation should be creating objects. If you want to create an array use brackets for example: "property[index].name"

null keys as part of a property path in array form should generate an Object, not an Array

'_.deepSet' wrongly assigns an Array when null is the courrent path element.

changing this line solved the problem for me:

/*
 *currentObject[property] = properties[index + 1] % 1 === 0 ? [] : {};
 * Above the _.isNull check is missing and null%1 ===0
 */
currentObject[property] = (!_.isNull(properties[index+1]) &&
   properties[index + 1] % 1 === 0) ? [] : {};

While x[null] is the same as x["null"] in regular objects _.deepSet(x,[null],val) is not the same as _.deepSet(x["null"]) or _.deepSet(x,"null").

What actually happens [in webkit] when you do var x=[]; x[null]=1 is that the array object property "null" is assigned.

Feature Request: _.deepPick , _.deepOmit

it would be great if you could use deep paths with pick and omit functions.

Example:

var response = {data: 123, trash: true, some: {garbage: '2890347jd'} }
var result = _.omit(response, ['trash', 'some.garbage'])
// { data : '123' }

Update package in npm

I need to access deep props defined by array, but latest version in npm cannot do it.

Great work!

@marklagendijk This probably isn't the right place to do this, so apologies in advance for muddying up the issue tracker, but I had been looking for a library like this one and was half way through writing my own when I discovered yours.

I've been perusing the source code and find it both readable and very well-written. Thank you for your work creating this wonderful complement to lodash!

Cant work with `instanceof File`

Hello mark,

i have an object like this

let aObject = {
   input : {
      aFile : instance of file
   }
}

with _.deepMapValues this not return path with input.aFile

my workaround for this s to modify else if and adding && !(object instanceof File) so this will not true and i can get the input.aFile path.

1.3 breaks for non-mixin case

My project was using lodash-deep@^1.2.1. A new developer joined and npm installed 1.3.0 which is OK in semver semantics. However, we are using lodash-deep without mixing it in to lodash itself: var deep = require('lodash-deep'); The code seems to assume you are mixing it because it accesses it's own extension functions via _, so it fails with this:

TypeError: Object function lodash(value) {
      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
      ? value
      : new lodashWrapper(value);
    } has no method 'deepIn'
 at Object.mixins.deepGet (/Users/kahboom/Projects/viaprotect-devtools/node_modules/lodash-deep/lodash-deep.js:61:9)

Property path as Object

How do you feel about letting propertyPath be an Object?

// Source Object
var collection = {
  foo: {
    bar: {
      baz: 'qux',
      asdf: 'qwerty'
    }
  }
};

_.deepGet(collection, {
  foo: {
    bar: {
      baz: 'localBazName',
      asdf: 'localAsdfName',
      wat: 'localWatName'
    }
  }
});

Result:

{
  "localBazName": "qux",
  "localAsdfName": "qwerty",
  "wat": undefined
}

New method: _.defaultsDeep

This is an attempt for _.defaultsDeep method from here.
One think that certainly is missing is making sure the source object stays intact.

_.mixin({
  'defaultsDeep': _.partialRight(_.merge, function recursiveDefaults () {
    // Ensure dates and arrays are not recursively merged
    if (_.isArray(arguments[0]) || _.isDate(arguments[0])) {
      return arguments[0];
    }
    return _.merge(arguments[0], arguments[1], recursiveDefaults);
  })
});

bower lodash-deep#a2768a72d7 ENORESTARGET Tag/branch a2768a72d7 does not exist

Hello,

When I run

bower install lodash-deep

I get the attached

$ bower install lodash-deep
bower lodash-deep#a2768a72d7 not-cached git://github.com/spenceralger/lodash-deep.git#a2768a72d7
bower lodash-deep#a2768a72d7 resolve git://github.com/spenceralger/lodash-deep.git#a2768a72d7
bower lodash-deep#* cached git://github.com/marklagendijk/lodash-deep.git#1.4.2
bower lodash-deep#* validate 1.4.2 against git://github.com/marklagendijk/lodash-deep.git#*
bower lodash#>=2.4.1 cached git://github.com/lodash/lodash.git#2.4.1
bower lodash#>=2.4.1 validate 2.4.1 against git://github.com/lodash/lodash.git#>=2.4.1
bower lodash-deep#a2768a72d7 ENORESTARGET Tag/branch a2768a7 does not exist

Is there a workaround or way to install locally to bower?

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.