Git Product home page Git Product logo

pydash's Introduction

pydash

version coveralls license

The kitchen sink of Python utility libraries for doing "stuff" in a functional way. Based on the Lo-Dash Javascript library.

Note

Looking for a library that is more memory efficient and better suited for large datasets? Check out fnc! It's built around generators and iteration and has iteratee-first function signatures.

pydash's People

Contributors

aetherunbound avatar andres-lowrie avatar ansont avatar beck3905 avatar bharadwajyarlagadda avatar bl4ckst0ne avatar deviousstoat avatar dgilland avatar elijose55 avatar expobrain avatar fnep avatar hohn avatar jeffwidman avatar jenstroeger avatar mervynlee94 avatar nathancahill avatar nathanrsmith avatar shaunpatterson avatar tgriesser avatar urbnjamesmi1 avatar weineel avatar zhaowb 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pydash's Issues

v1.1.0 function port status

Status listing of Lo-Dash functions ported to pydash.

Lo-Dash v3.0.0 (pre)

Arrays

  • _.chunk
  • _.dropRight
  • _.dropRightWhile
  • _.dropWhile
  • _.pullAt
  • _.slice
  • _.sortedLastIndex
  • _.takeRight
  • _.takeRightWhile
  • _.takeWhile

Collections

  • _.partition

Functions

  • _.before
  • _.curryRight
  • _.negate

Objects

  • _.isError
  • _.keysIn
  • _.valuesIn

Utilities

  • _.attempt
  • _.matches

Strings

  • _.camelCase
  • _.capitalize
  • _.endsWith
  • _.escapeRegExp
  • _.kebabCase
  • _.pad
  • _.padLeft
  • _.padRight
  • _.repeat
  • _.snakeCase
  • _.startsWith
  • _.template will not be a part of v1.1.0; may be included in a future release
  • _.trim
  • _.trimLeft
  • _.trimRight
  • _.trunc

This library is amazing

I do a lot of development using lodash and lodash-fp. I got to say, this library is a godsend for similar functionality in Python. It makes porting existing lodash-centric logic a lot easier as well. I hope this project doesn't die. Is there some sort of established relationship with lodash itself? We should promote the use of this more.
Thanks for your efforts ๐Ÿ‘

keys() should work with lists

In Lo-Dash:

_.keys([1, 2, 3]) == ['1', '2', '3']

In pydash:

pydash.keys([1,2,3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydash/objects.py", line 200, in keys
    return list(iterkeys(obj))
  File "pydash/_compat.py", line 36, in <lambda>
    iterkeys = lambda d: d.iterkeys()
AttributeError: 'list' object has no attribute 'iterkeys'

NOTE: Even though Lo-Dash returns string keys, pydash should use integers.

invert() should work with lists

In Lo-Dash:

_.invert([1,2,3]) == {'1': '0', '2': '1', '3': '2'}

In pydash:

pydash.invert([1,2,3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydash/objects.py", line 153, in invert
    return dict((value, key) for key, value in iteritems(obj))
  File "pydash/_compat.py", line 38, in <lambda>
    iteritems = lambda d: d.iteritems()
AttributeError: 'list' object has no attribute 'iteritems'

NOTE: Even though Lo-Dash returns string keys, pydash should use integers.

pairs() should work with lists

In Lo-Dash:

_.pairs([1, 2, 3]) == [['0', 1], ['1', 1], ['2', 2]]

In pydash:

pydash.pairs([1, 2, 3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydash/objects.py", line 308, in pairs
    return [[key, value] for key, value in iteritems(obj)]
  File "pydash/_compat.py", line 38, in <lambda>
    iteritems = lambda d: d.iteritems()
AttributeError: 'list' object has no attribute 'iteritems'

NOTE: Even though Lo-Dash returns string keys, pydash should use integers.

values() should work with lists

In Lo-Dash:

_.values([1, 2, 3]) == [1, 2, 3]

In pydash:

pydash.values([1, 2, 3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydash/objects.py", line 350, in values
    return list(itervalues(obj))
  File "pydash/_compat.py", line 37, in <lambda>
    itervalues = lambda d: d.itervalues()
AttributeError: 'list' object has no attribute 'itervalues'

Port underscore.string

Project: https://github.com/epeli/underscore.string

Functions:

  • numberFormat
  • levenshtein (punting on this; will defer to other libraries which focus solely on this)
  • capitalize
  • decapitalize
  • chop
  • clean
  • chars
  • swapCase
  • include (as has_substr since include already used in collections)
  • count (as count_substr since count is too generic)
  • escapeHTML (as escape)
  • unescapeHTML (as unescape)
  • insert (as insert_substr)
  • replaceAll (as replace)
  • isBlank
  • join (as implode)
  • lines
  • reverse (in pydash.arrays; works for both lists and strings)
  • splice
  • startsWith
  • endsWith
  • pred
  • succ
  • titleize (as title_case)
  • camelize (as camel_case)
  • classify (as class_case)
  • underscored (as snake_case)
  • dasherize (punting on this, it appears that dasherize behaves slightly different than kebab_case in that dasherize will append a - to the beginning of the string; consider adding dash_case as a separate function)
  • humanize (as human_case)
  • trim
  • ltrim
  • rtrim
  • truncate
  • prune
  • words
  • sprintf (punting on this for now. Python already has string format functions but it may be worth having a chainable function for this)
  • pad (functions as lrpad)
  • lpad (as pad_left)
  • rpad (as pad_right)
  • lrpad (as pad)
  • toNumber
  • strRight (as string_right)
  • strRightBack (as string_right_back)
  • strLeft (as string_left)
  • strLeftBack (as string_left_back)
  • stripTags
  • toSentence (as series_phrase)
  • toSentenceSerial (as series_phrase_serial)
  • repeat
  • surround
  • quote
  • unquote
  • slugify
  • naturalCmp (punting on this, there's a natural sort lib that does this: natsort)
  • toBoolean

merge() results in linked dicts

Failing test case:

some_dict = {'foo': {'bar': None}}
new_dict = merge({}, some_dict)
new_dict['foo']['bar'] = 'baz'
assert some_dict['foo']['bar'] == new_dict['foo']['bar']

Expected:

assert some_dict['foo']['bar'] is None

deep_get cannot index nested arrays

Is this supposed to work in pydash?

In [4]: o=[{"hits":{"hits":[{"_source":5}]}}]

In [5]: pydash.deep_get(o, '[0].hits.hits[0]._source') # this is supposed to return 5

In [6]: pydash.deep_get(o, '[0].hits.hits')
Out[6]: [{'_source': 5}]

In [7]: pydash.deep_get(o, '[0].hits.hits[0]')

It works fine in lodash:

> o=[{"hits":{"hits":[{"_source":5}]}}]
[ { hits: { hits: [Object] } } ]
> l.get(o, '[0].hits.hits[0]._source')
5

objects.merge docs don't match implementation

In particular, docs for merge say:

If the callback returns undefined merging will be handled by the method instead.

undefined in this context appears to be an artifact of a port from lodash... and looking at the implementation, the result of the callback is not considered.

The easy fix is to delete that sentence. Perhaps better would be to implement support for that functionality, perhaps by testing for is NoValue, and update the documentation to match that.

Why does pydash have map_?

Hi there,

Great work on this library, super useful as someone who comes from the JS lodash world.

I was wondering why pydash duplicates in-built functions such as map, given that pydash equivalents are significantly slower when benchmarked with %timeit in ipynb.

Just Curious: Why so slow?

As a precursor to my question: I'm not here to cast doubt upon the usefulness of this project or the adequacy of those who have worked on it. In truth I am very impressed by this project and when I first discovered it I began using it in most of my projects! (I do lots of data mining, so a library such as this is priceless.)

But I noticed recently that some of the functions in Pydash are very slow compared to their Python counterparts. For instance consider the following code:

from pydash import filter_

In [.]: x = [{'a': 1, 'b': 2, 'c': 3}, {'a': 2, 'b': 3, 'c': 4}]
In [.]: %timeit filter_(x, {'a': 1})
10000 loops, best of 3: 62.1 ยตs per loop

In [.]: %timeit filter(lambda y: y['a'] is 1, x)
1000000 loops, best of 3: 417 ns per loop

Now in truth I would never expect the Pydash equivalent functions to be faster than the Python counterpart, but ~150x slower?

Any idea how the speed of these functions could be improved? Since I made this performance discovery I've stopped using the pydash library so much and went back to filter + lambda...but goodness that can get ugly! I love the idea of this library, I just wished performance was better.

v1.0.0 function port status

Status listing of Lo-Dash functions ported to pydash.

Lo-Dash v2.4.1

Arrays

  • _.compact
  • _.difference
  • _.drop โ†’ rest
  • _.findIndex
  • _.findLastIndex
  • _.first
  • _.flatten
  • _.head โ†’ first
  • _.indexOf
  • _.initial
  • _.intersection
  • _.last
  • _.lastIndexOf
  • _.object โ†’ zipObject
  • _.pull
  • _.range
  • _.remove
  • _.rest
  • _.sortedIndex
  • _.tail โ†’ rest
  • _.take โ†’ first
  • _.union
  • _.uniq
  • _.unique โ†’ uniq
  • _.unzip โ†’ zip
  • _.without
  • _.xor
  • _.zip
  • _.zipObject

Chaining

  • _ (Implementing the pydash module as a callable seems to involve having to make some class instance masquerade as the module ร  la sys.modules[__name__] = SomeClass() where SomeClass() would then have access to all of the pydash methods. Not sure whether it's worth the complexity and mild hackery needed to have this feature.)
  • _.chain
  • _.tap
  • _.prototype.chain
  • _.prototype.toString
  • _.prototype.value โ†’ valueOf
  • _.prototype.valueOf

Collections

  • _.all โ†’ every
  • _.any โ†’ some
  • _.at
  • _.collect โ†’ map
  • _.contains
  • _.countBy
  • _.detect โ†’ find
  • _.each โ†’ forEach
  • _.eachRight โ†’ forEachRight
  • _.every
  • _.filter
  • _.find
  • _.findLast
  • _.findWhere โ†’ find
  • _.foldl โ†’ reduce
  • _.foldr โ†’ reduceRight
  • _.forEach
  • _.forEachRight
  • _.groupBy
  • _.include โ†’ contains
  • _.indexBy
  • _.inject โ†’ reduce
  • _.invoke
  • _.map
  • _.max
  • _.min
  • _.pluck
  • _.reduce
  • _.reduceRight
  • _.reject
  • _.sample
  • _.select โ†’ filter
  • _.shuffle
  • _.size
  • _.some
  • _.sortBy
  • _.toArray
  • _.where

Functions

  • _.after
  • _.bind
  • _.bindAll
  • _.bindKey
  • _.compose
  • _.curry
  • _.debounce
  • _.defer
  • _.delay
  • _.memoize
  • _.once
  • _.partial
  • _.partialRight
  • _.throttle
  • _.wrap

Objects

  • _.assign
  • _.clone
  • _.cloneDeep
  • _.create
  • _.defaults
  • _.extend โ†’ assign
  • _.findKey
  • _.findLastKey
  • _.forIn
  • _.forInRight
  • _.forOwn
  • _.forOwnRight
  • _.functions
  • _.has
  • _.invert
  • _.isArguments
  • _.isArray
  • _.isBoolean
  • _.isDate
  • _.isElement
  • _.isEmpty
  • _.isEqual
  • _.isFinite
  • _.isFunction
  • _.isNaN
  • _.isNull
  • _.isNumber
  • _.isObject
  • _.isPlainObject
  • _.isRegExp
  • _.isString
  • _.isUndefined
  • _.keys
  • _.mapValues
  • _.merge
  • _.methods โ†’ functions
  • _.omit
  • _.pairs
  • _.pick
  • _.transform
  • _.values

Utilities

  • _.now
  • _.constant
  • _.callback
  • _.escape
  • _.identity
  • _.mixin
  • _.noConflict
  • _.noop
  • _.parseInt
  • _.property
  • _.random
  • _.result
  • _.runInContext
  • _.template may be implemented in future version
  • _.times
  • _.unescape
  • _.uniqueId

Concatenating None

Concatenating when source is None produces the following:

pydash.concat(None, [1]) == [None,1]

The expected output is:

pydash.concat(None, [1]) == [1]

Happens in Pydash 3.4.8 and 4.0.3 under macOS 10.12.4, Python 3.4.

PS: magnificent library!

pick() should work with lists

In Lo-Dash:

_.pick([1, 2, 3], 0) == {'0': 1}

In pydash:

pydash.pick([1,2,3], 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydash/objects.py", line 322, in pick
    return dict((key, value) for key, value in iteritems(obj)
  File "pydash/_compat.py", line 38, in <lambda>
    iteritems = lambda d: d.iteritems()
AttributeError: 'list' object has no attribute 'iteritems'

NOTE: Even though Lo-Dash returns string keys, pydash should use integers.

Resolve circular import issues

Relevant warts:

Refs #9

Possible solutions:

  1. Keep circular imports in place.
  2. Move common functions to utils.py and alias into corresponding file (e.g. move collections.where to utils.whereand then create an alias towhereincollections`).
  3. Use an absolute import of pydash in target files and then reference circular dependencies through that.

Allow late passing of value to pydash.chain

Implement the following use case:

square_sum = pydash.chain().power(2).sum()

# possibly use a method called "execute"
assert square_sum.execute([1, 2, 3, 4]) == 30

# or maybe even allow __call__ to work
assert square_sum([1, 2, 3, 4]) == 30

get goes b00m

This is fine:

from pydash import (
    get
)
cow = {'Body': {'result': True}}
print("cow: " + str(cow))
grab = get(cow, 'Body.result', False)
print("grab: " + str(grab))

However, change 'Body' to lowercase in the get:

grab = get(cow, 'body.result', False)

... and she ain't so safe anymore, doesn't return false and instead raises this:

Traceback (most recent call last):
  File "testing.py", line 6, in <module>
    grab = get(cow, 'body.result', False)
  File "/Users/lpq389/myenv/lib/python2.7/site-packages/pydash/objects.py", line 511, in get
    obj = get_item(obj, key, default=default)
  File "/Users/lpq389/myenv/lib/python2.7/site-packages/pydash/helpers.py", line 128, in get_item
    ret = obj[int(key)]
ValueError: invalid literal for int() with base 10: 'result'

I'm looking at the code now to see if I can fix (I suck at Python, hence my life depending on Pydash). Workaround is to just wrap her in a try/except.

no replacement for deep_pluck with list argument

With the upgrade to version 4, there seems to be no equal replacement for deep_pluck with a list as argument.The recommended .map call has a different behavior.

Version 3.4.8:

>>> py_.deep_pluck([{1: {2: {3: 4}}}], [1, 2])
[{3: 4}]

Version 4.0.0:

>>> py_.map([{1: {2: {3: 4}}}], [1, 2])
[False]

The only workaround i found was:

>>> py_.map([{1: {2: {3: 4}}}], py_.property_deep([1, 2]))
[{3: 4}]

Remove all alias functions

Time to get rid of aliases to cut down on the multitude of different ways to invoke the same function. This is primarily to help enforce the "there should be one way to do it" mantra of Python within other libraries/applications that use pydash. Having the potential for different function names that call the same function can make debugging more difficult and grepping harder since you have to take into account all the aliases of a function to find where it is being used.

Can use Lodash's own deprecations page as a guide but I'd like to eliminate all aliases.

Ensure string ends with a given suffix

I suggest adding a function which appends a given suffix to a string, but only if the source string does not end with that suffix.

def ensure_ends_with(text, suffix):
    """Append a given suffix to a string, but only if the source string does not end with that suffix.
        Args:
            text (str): Source string to append `suffix` to
            suffix (str): String to append to the source string if the source string does not end with `suffix`
        Returns:
            str: source string possibly extended by `suffix`
        .. versionadded:: 2.0.0
    """
    return text if text.endsWith(suffix) else text + suffix

As I'm not a native speaker, for me it's not clear how to name that function. My suggestion is ensure_ends_withor is make_ending_with better?

When get_item returns the default value, pydash.objects.get continues evaluating the key path

If the remaining keys are in the default value, you'll get the value inside the default value supplied to get instead of the default value itself.

Operating System: Mac OS X 10.11.5 (El Capitan)
Steps to reproduce:

  1. In a python REPL with pydash installed, type:
import pydash

obj = {'one': {'two': {'three': 4}}}
default_value = [{'a': 1}]
value = pydash.get(obj, 'one.four.0.a', default=default_value)
value
  1. value will be 1 instead of [{'a': 1}] because while processing the 'four' key, get_item returns the default value and get continues with '0.a'

omit() should work with lists

In Lo-Dash:

.omit([1,2,3]) == {'0': 1, '1': 2, '2': 3}

In pydash

pydash.omit([1, 2, 3], lambda x, *args: x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydash/objects.py", line 300, in omit
    return dict((key, value) for key, value in iteritems(obj)
  File "pydash/_compat.py", line 38, in <lambda>
    iteritems = lambda d: d.iteritems()
AttributeError: 'list' object has no attribute 'iteritems'

NOTE: Even though Lo-Dash returns string keys, pydash should use integers.

Add LoDash functions

Arrays

  • difference_by
  • difference_with
  • flatten_depth
  • from_pairs
  • intersection_by
  • intersection_with
  • nth
  • pull_all
  • pull_all_by
  • pull_all_with
  • sorted_index_by
  • sorted_index_of
  • sorted_last_index_by
  • sorted_last_index_of
  • sorted_uniq
  • sorted_uniq_by
  • union_by
  • union_with
  • uniq_by
  • uniq_with
  • xor_by
  • xor_with
  • zip_object_deep

Collections

  • flat_map
  • flat_map_deep
  • flat_map_depth
  • invoke_map
  • sample_size

Objects

  • assign_with
  • clone_deep_with
  • clone_with
  • invert_by
  • merge_with
  • omit_by
  • pick_by
  • set_with
  • to_integer
  • unset
  • update
  • update_with

Predicates

  • eq
  • is_equal_with
  • is_match_with
  • is_set

Strings

  • lower_case
  • lower_first
  • upper_case
  • upper_first
  • to_lower
  • to_upper

Numerical

  • clamp
  • mean_by
  • max_by
  • min_by
  • sum_by
  • subtract
  • divide
  • multiply

Functions

  • flip
  • unary

Utilities

  • cond
  • conforms
  • conforms_to
  • default_to
  • nth_arg
  • over
  • over_every
  • over_some
  • range_right
  • stub_array (or maybe stub_list?)
  • stub_object (or maybe stub_dict?)
  • stub_string
  • stub_false
  • stub_true
  • to_path

default value for max_, min_

It'll be very useful to be able to pass in default value for empty collections (like Python3)
coll = []
max_(coll, callback=lambda x: x*x, default=0)

currently, it'll error with max() arg

py_.intersection returns an empty set if no *others are given

This is a difference between 4.0.1 and 3.4.8 that i cannot really resolve.

$ pip install pydash==3.4.8
>>> py_.intersection([1, 2, 3], [1, 2])
[1, 2]
>>> py_.intersection([1, 2, 3])
[1, 2, 3]

And now:

$ pip install pydash==4.0.1
>>> py_.intersection([1, 2, 3], [1, 2])
[1, 2]
>>> py_.intersection([1, 2, 3])
[]

I call py_.intersection with a set of arrays like common_values = py_.intersection(*list_of_lists), so i run into this problem if my list_of_lists contains only a single list.

Port status of lodash-contrib

Array Builders

  • cat
  • mapcat
  • reductions
  • splitAt

Array Selectors

None

Collection Walk

None

Airty

None

Function Combinators

  • conjoin
  • disjoin
  • juxt

Function Iterators

None

Function Predicates

  • isAssociative
  • isDecreasing
  • isEven
  • isFloat
  • isIncreasing
  • isIndexed
  • isInstanceOf
  • isInteger
  • isJSON
  • isNegative
  • isOdd
  • isPositive
  • isZero

Object Builders

  • renameKeys
  • setPath
  • updatePath

Object Selectors

  • getPath
  • hasPath

Util Existential

None

Util Operators

This module is almost identical to Python's operator. Consider adding the operator module's functions as aliases.

None

Util Strings

  • explode
  • implode

Util Trampolines

None

Current status of this project?

Hey, I'm a great admirer of lodash and searching for a python replacement for it.
Isn't on pypi, not manifest file or setup.py. so no way to install now. Is this in active development?

ValueError: invalid literal for int() with base 10 in get

Operating System: MacOS X 10.11.5 (El Capitan)
Python versions: 2.7, 3.4, 3.5
Pydash version: 3.4.5
Reproduction steps:

  1. In a Python virtualenv with pydash as a pip dependency, open a Python REPL and enter:
import pydash
a = { 'a': { 'b': { 'c': { 'd': [] } } } }
pydash.get(a, 'a.b.e.d', [])
  1. You will get a TypeError stating that list indices must be integers, not str, followed by:
ValueError: invalid literal for int() with base 10: 'd'

It should have returned the default value []

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.