Package: recurtools
recurtoolsSo many questions on StackExchange take the form "How do I ... with a nested list?".
Here are some tools and helpers I developed to solve those kinds of problemsWARNINGThis is a 0.x.x version because I am not yet happy with the function naming. Expect the API to change.
v0.4.0 made breaking changes to string handling inflatten- see Changelog for more details.Currently standard functionality is to traverse left-to-right as the collection would be output byprint()Getting StartedInstallationpip install recurtoolsflattenA generator which will flatten any iterable collection recursively.fromrecurtoolsimportflatteninput=[1,2,[3,4,[5],6],7,[8,9]]assert[xforxinflatten(input)]==[1,2,3,4,5,6,7,8,9]New in 0.3.0: Optional argumentpreservestrings(default:False) will not flatten strings:fromrecurtoolsimportflatteninput=['ab',3,('cd','e')]assert[xforxinflatten(input,preservestrings=True)]==['ab',3,'cd','e']nestedAContainerwhich implementslenrecursive,countrecursive,inrecursiveandflattenforlen(),.count(),inandfor x infromrecurtoolsimportnestedinput=[1,2,[3,4,[5],6],7,[8,9]]nest=nested(input)assertlen(nest)==9assert4innestassert0notinnestout=[xforxinnest]assertout==[1,2,3,4,5,6,7,8,9]nest2=nested([1,2,[3,2,[5],6],7,[2,9]])assertnest2.count(2)==3lenrecursive, sumrecursive, countrecursive, inrecursiveRecursive versions oflen,sum,count,inandindex.Generally these will return a 0 orNonevalue rather than raising anTypeErrororValueErroras their nonrecursive brethren do.indexrecursiveis an exception and will raise a specificNotFoundError.They can also cope with situations where some elements in the nested collection are summable / have a length etc. and others do not.fromrecurtoolsimportlenrecursiveassertlenrecursive([1,2,[3,4]])==4assertlenrecursive([1,2,[3,4]],countcontainers=True)==5fromrecurtoolsimportsumrecursiveassertsumrecursive([1,2,[3,4]])==10assertsumrecursive([1,2.5,[4,"foo"],(5,(0.5,5))])==18fromrecurtoolsimportcountrecursiveassertcountrecursive([1,2,[3,2]],2)==2assertcountrecursive(["ab","b",["c","db",["e","bob"]]],'b')==5fromrecurtoolsimportinrecursiveassertinrecursive([1,2,[3,2]],3)==Truefromrecurtoolsimportindexrecursiveassertindexrecursive([1,2,[3,2]],2)==(1,)assertindexrecursive([1,2,[3,2]],3)==(2,0)assertindexrecursive(["Foo",[1,"Bar"]],"a")==(1,1,1)withraises(NotFoundError):indexrecursive([1,2,[3,2]],4)chainanythingA generator that chains (m)anything(s).fromrecurtoolsimportchainanythinga=[1,2,3]b="de"c=5d=[4,5,23,11,5]e=["dg","kuku"]assert[xforxinchainanything(a,b,c,d,e)]==[1,2,3,"de",5,4,5,23,11,5,"dg","kuku"]assert''.join(map(str,chainanything(a,b,c,d,e)))=="123de54523115dgkuku"preservestrings = False will lead to strings being yielded as individual characters. Default =Truerecursive = True will recursively flatten container. Default =False(Warning: This may change in v1.0.0)Note: preservestrings = False, recursive = False will only flatten strings which are not part of another container.
e.g.: 'abc' -> 'a','b','c' but ['ab','cd'] -> 'ab','cd'a=[1,2,3]b="de"c=5d=[4,5,23,11,5]e=["dg","kuku"]assert[xforxinchainanything(a,b,c,d,e,recursive=False,preservestrings=False)]==[1,2,3,"d","e",5,4,5,23,11,5,"dg","kuku"]assert[xforxinchainanything(a,b,c,d,e,recursive=True,preservestrings=False)]==[1,2,3,"d","e",5,4,5,23,11,5,"d","g","k","u","k","u"]