Package: python-ramda
python_ramdaThis is a repo try to copyhttps://github.com/ramda/ramdain python.installFor whom wants to use this package.>pipinstallpython-ramda
>pipinstallpython-ramda-U# get the latestUsage>>>fromramdaimportcurry>>>defsum(a,b,c):returna+b+c>>>curry(sum)(1)(2,3)6>>>importramdaasR# similar to ramda syntax>>>defsum(a,b,c):returna+b+c>>>R.curry(sum)(1)(2,3)6DocBecause the usage ofpython_ramdais almostly same toramda,
so we don't create any extra doc.If you feel any behaviour is different from what is should be inramda,
please check belowCheckListfor more details.ContributeFor whom wants to contribute to this repo.$pipinstall-Upylint# see: https://pre-commit.com/ for more details$pre-commitinstall# please install hooks firstCheckout new branch frommainbranch directly and create PR.CheckListFunctions supported now.0.1.2 __0.1.2 add# different from ramdaR.add(None,None)# float('nan)R.add(date(1,2,3),date(1,2,3))# float('nan)addIndex0.1.2 adjust0.1.2 allTransducer part is not fully tested.allPass0.1.2 always0.1.2 And (andis a keyword in python)andThen0.1.2 anyanyPass0.3.0 apaperture0.1.2 append0.7.0 applyapplySpecapplyToascend0.8.0 assocCurrently, we only support list and dict type.0.8.0 assocPathCurrently, we only support list and dict type.0.2.0 binarybindbothcall0.3.0 chainclamp0.1.2 clonewe are simply using pythoncopymoduleSo with no specific reason, we suggest you to use python origincopymodule as your first choice.classObj:def__init__(self,x):self.value=xobj=Obj(42)clone=R.clone(obj)obj==clone# False, obj and clone have different referencesisinstance(clone,Obj)# TrueclassObj:def__init__(self,x):self.value=xdef__eq__(self,other):returnself.value==other.valueobj=Obj(42)clone=R.clone(obj)obj==clone# True, if Obj override __eq__ functionisinstance(clone,Obj)# TruecollectBy0.1.2 comparatorcomplement0.1.2 composecomposeWith0.1.2 concat0.6.0 condPlease notice the number of given arguments should match functions.
Otherwise Python will complain about the mis-matching arguments.For example:fn=R.cond([[lambdaa:a==1,lambdaa:f'a =={a}'],[lambdaa,b:a==b,lambdaa,b:f'{a}=={b}']])fn(1)# a == 1fn(2,2)# 2 == 2fn(2)# Throw error, because b is not provided for prediction, failed when (lambda a, b: a == b)(2), missing argument b# to solve above issue, you should try your best to provide enough argumentsfn(1,2)# Throw error, because (lambda(a: f'a == {a}'))(1, 2) has extra arguments 2# To solve above issue, always use sencond function with enough arguments# Try create cond like below.fn=R.cond([[lambdaa:a==1,lambdaa,_:f'a =={a}'],# ignore b[lambdaa,b:a==b,lambdaa,b:f'{a}=={b}']])fn=R.cond([[lambdaa:a==1,lambdaa,*args:f'a =={a}'],# ignore any arguments[lambdaa,b:a==b,lambdaa,b:f'{a}=={b}']])0.4.0 construct0.4.0 constructN0.1.4 convergecount0.1.2 countBy0.1.2 curry0.1.2 curryNdec0.6.0 defaultTodescend0.1.2 difference0.1.2 differenceWithdissocdissocPath0.1.2 divide0.1.2 dropdropLastdropLastWhiledropRepeatsdropRepeatsWithdropWhileeither0.1.2 empty# We don't support empty object in pythonclassObj:def__init__(self,value):self.value=valueo=Obj(42)o==R.empty(o)# True, we will return the original cloned objectWhat we support for now:dict()set()list()str()any instance with empty() methodany instance with 'fantasy-land/empty' propertyendsWitheqBy0.1.2 eqProps# works for both dict and objectclassObj:def__init__(self,v):self.v=vobj1=Obj(1)obj2=Obj(1)R.eqProps('v',obj1,obj2)# TrueR.eqProps('v',{'v':1},{'v':1})# True0.1.2 equalsR.equals(float('nan'),float('nan'))# Trueevolve0.1.2 F0.1.2 filter0.1.2 find0.1.4 findIndex0.1.4 findLast0.1.4 findLastIndex0.1.2 flatten0.1.2 flip0.1.4 forEachforEachObjIndexed0.3.0 fromPairs0.1.2 groupBygroupWith0.1.2 gt0.1.2 gte0.7.0 hasSimilar tohasPath.0.7.0 hasInworks for both dict and objectclassObj:def__init__(self,v):self.v=vobj1=Obj(1)R.hasIn('v',obj1)# TrueR.hasIn('v',{'v':1})# TruehasPath
Support both dict and object.R.hasPath(['a','b'],{'a':{'b':42}})# TrueclassObj:def__init__(self,v):self.v=vobj=Obj(1)R.hasPath(['v'],obj)# TrueR.hasPath(['v','child'],obj)# FalseR.hasPath(['v'],{'v':1})# TrueR.hasPath(['v','child'],{'v':1})# False# Does not include static variableclassObj:v=1obj=Obj()R.hasPath(['v'],obj)# False# Also support inherited variableclassParent:def__init__(self,a):self.a=aclassChild(Parent):def__init__(self,a,b):super().__init__(a)self.b=bchild=Child(1,2)R.hasPath(['a'],child)# TrueR.hasPath(['b'],child)# True0.1.2 headidentical0.1.2 identity0.8.0 ifElseincincludesindexBy0.1.2 indexOfinitinnerJoin0.2.2 insertinsertAll0.1.2 intersectionintersperse0.1.2 intoinvertinvertObj0.1.2 invoker0.3.0 Is (isis a keyword in python)This is a language specific feature.
So we check all python built-in types as many as we can.R.Is(int,1)# TrueR.Is(float,1.0)# TrueR.Is(str,'1')# TrueR.Is(list,[1,2,3])# TrueR.Is(dict,{'a':1})# TrueR.Is(set,{1,2,3})# TrueR.Is(tuple,(1,2,3))# TrueR.Is(None,None)# TrueR.Is(bool,True)# TrueR.Is(bool,False)# True# For user-defined objectclassParent:passclassChild(Parent):passR.Is(Parent,Parent())# TrueR.Is(Parent,Child())# TrueR.Is(Child,Child())# TrueR.Is(Child,Parent())# False0.1.2 isEmptyclassObj:pass# Any custom object will be treated as non-emptyR.isEmpty(Obj())# FalseR.isEmpty(None)# FalseisNilWe keep the same method name as ramda,
this is for checking if the given value is None or not.0.1.2 join0.1.4 juxt0.1.2 keysFor object,keysdoes not return object's methods.# When using R.keys(obj) and obj is a class instance, we use obj.__dict__ as keys.classA:c='not included'def__init__(self):self.a=1self.b=2a=A()R.keys(a)# ['a', 'b']# keys include super class attributesclassA:def__init__(self,a):self.a=aclassB(A):def__init__(self,a,b):super().__init__(a)self.b=bclassC(A):def__init__(self,c):self.c=ca=A(1)b=B(2,3)c=C(4)R.keys(a)# ['a']R.keys(b)# ['a', 'b']R.keys(c)# ['c'], because c does not call super().__init__()# For normal dictR.keys({'a':1,'b':2})# ['a', 'b']0.2.0 keysInFor object,keysIndoes not return object's methods.Different fromkeys,keysInwill return all attributes of the object, including super class attributes and class static variables.classA:a_static=1def__init__(self):self.a=1classB(A):b_static=2def__init__(self,b):super().__init__()self.b=bR.keysIn(A())# ['a_static', 'a']R.keysIn(B(2))# ['a_static', 'a', 'b_static', 'b']# For normal dictR.keysIn({'a':1,'b':2})# ['a', 'b']0.1.4 last0.1.2 lastIndexOf0.3.0 lengthThe behavior oflengthis different fromramda.# ArrayR.length([1,2,3])# 3# StringR.length('abc')# 3# DictR.length({'a':1,'b':2})# 2# SetR.length({1,2,3})# 3# TupleR.length((1,2,3))# 3# Notice: Also works for any other iterable object# Some special cases# object with length() methodclassObj:deflength(self):return3obj=Obj()R.length(obj)# 3# dict with length propertyR.length({'a':1,'length':99})# 99, R.length will use length property instead# return function arguments lengthdeff(a,b,c):returna+b+cR.length(f)# 3# Any failed cases, return nan insteadR.length(None)# float('nan')R.length(1)# float('nan')classObjWithoutLength:passR.length(ObjWithoutLength())# float('nan')0.8.0 lenslensIndexlensPathlensProp0.7.0 lift0.7.0 liftN0.1.2 lt0.1.2 lte0.1.2 mapmapAccummapAccumRightmapObjIndexed0.1.2 match0.3.0 mathMod0.1.2 Max (maxis a keyword in python)If R.Max(a, b)aandbare with different types,
we will compare with str(a) and str(b).R.Max('A',None)# None, 'A' < 'None'0.8.0 maxBymeanmedianmemoizeWithmergeAllmergeDeepLeftmergeDeepRightmergeDeepWithmergeDeepWithKeymergeLeftmergeRightmergeWithmergeWithKey0.1.2 Min (minis a keyword in python)If R.Min(a, b)aandbare with different types,
we will compare with str(a) and str(b).R.Min('A',None)# 'A', 'A' < 'None'0.8.0 minBymodifymodifyPath0.1.4 moduloPython modulo on negative numbers has different behavior than JS.5%-3# -15%-3;// 2move0.1.2 multiply0.2.0 nArynegatenone0.1.2 not0.1.2 nthnthArgo0.1.2 objOf0.3.0 of0.1.2 omitwe support bothdicttype andobjecttype.classObj:def__init__(self,v1,v2):self.v1=v1self.v2=v2obj=Obj(1,2)R.omit(['v1'],obj)# {'v2': 2}R.omit(['v1','v3'],obj)# {'v2': 2}on0.1.2 once0.1.2 orotherwiseoverpairpartialpartialObjectpartialRight0.1.4 partition0.1.2 path0.7.0 pathEqpathOr0.1.2 pathspathSatisfies0.1.2 pick0.1.2 pickAllbothpickandpickAllsupport bothdictandobjecttype.classObj:def__init__(self,v1,v2):self.v1=v1self.v2=v2obj=Obj(1,2)R.pick(['v1'],obj)# {'v1': 1}R.pickAll(['v1','v3'],obj)# {'v1': 1, 'v3': None}0.8.0 pickBy0.1.2 pipepipeWith0.1.2 pluck# works for both dict and objectclassObj:def__init__(self,v1,v2):self.v1=v1self.v2=v2obj1=Obj(1,2)obj2=Obj(3,4)R.pluck('v1',[obj1,obj2])# [1, 3]0.1.2 prepend0.1.2 product0.1.2 project# works for both dict and objectclassObj:def__init__(self,v1,v2):self.v1=v1self.v2=v2obj1=Obj(1,2)obj2=Obj(3,4)R.project(['v1'],[obj1,obj2])# [{'v1': 1}, {'v1': 3}]promap0.1.2 prop0.1.2 propEq# works for both dict and objectclassObj:def__init__(self,v1,v2):self.v1=v1self.v2=v2obj1=Obj(1,2)R.propEq(1,'v1',obj1)# TrueR.propEq(2,'v2',obj1)# TrueR.propEq(1,'v2',obj1)# FalseR.propEq(1,'v1',{'v1':1})# TruepropIs0.6.0 propOr0.1.2 propspropSatisfies0.1.2 range0.1.2 reduce0.1.2 reduceBy0.1.2 reduced0.1.2 reduceRightreduceWhile0.1.2 reject0.2.2 remove0.1.4 repeat0.7.0 replace0.1.2 reversescansequenceset0.1.2 sliceR.slice(1,3,['a','b','c','d'])# ['b', 'c']R.slice(1,None,['a','b','c','d'])# ['b', 'c', 'd']0.1.2 sort0.1.2 sortBysortWith0.1.2 splitsplitAtsplitEverysplitWhensplitWheneverstartsWith0.1.2 subtract# different from ramdaR.subtract(None,None)# float('nan)R.subtract(date(1,2,3),date(1,2,3))# float('nan)0.1.2 sumsymmetricDifferencesymmetricDifferenceWith0.1.2 T0.1.2 tail0.1.2 taketakeLasttakeLastWhile0.1.2 takeWhile0.1.2 taptestthunkify0.1.4 timestoLower0.4.0 toPairsR.toPairs({'a':1,'b':2})# [['a', 1], ['b', 2]]classA:v1='not included'def__init__(self,v2):self.v2=v2R.toPairs(A(1))# [['v2', 1]]classB(A):v3='not included'def__init__(self,v2,v4):super().__init__(v2)# this is requiredself.v4=v4b=B('v2','v4')R.toPairs(b)# [['v2', 'v2'], ['v4', 'v4']]0.4.0 toPairsInR.toPairsIn({'a':1,'b':2})# [['a', 1], ['b', 2]]classA:v1='included'def__init__(self,v2):self.v2=v2R.toPairsIn(A('v2'))# [['v1', 'included'], ['v2', 'v2']]classB(A):v3='included too'def__init__(self,v2,v4):super().__init__(v2)# this is requiredself.v4=v4R.toPairsIn(B('v2','v4'))# [['v3', 'included too'], ['v1', 'included'], ['v2', 'v2'], ['v4', 'v4']]0.1.2 toStringPartially supportedString type, supportedfor others, just use str(x) insteadtoUppertransducetransposetraverse0.6.0 trimtryCatchtype0.8.0 unapply0.2.0 unaryuncurryNunfold0.1.2 union0.1.2 unionWith0.1.2 uniq0.1.2 uniqBy0.1.2 uniqWithunless0.3.0 unnestuntilunwindupdate0.1.2 useWith0.1.2 values# works for both dict and objectclassObj:def__init__(self,v1,v2):self.v1=v1self.v2=v2obj=Obj(1,2)R.values(obj)# [1, 2]R.values({'a':1,'b':2})# [1, 2]0.2.0 valuesInUseR.keysInto get the keys of an object.viewwhen0.1.4 wherespec(first param) is prefer to be a dict.methodwheresupports both dict and object as second param.classObj:def__init__(self,x,y):self.x=xself.y=yspec={'x':R.equals(1)}R.where(spec,{'x':1,'y':2})# TrueR.where(spec,Obj(1,2))# TruewhereAnywhereEqwithoutxor0.1.2 xprod0.1.2 zip0.3.0 zipObjIt will return a dict.0.1.2 zipWith