Package: amnis
█████╗ ███╗   ███╗███╗   ██╗██╗███████╗
██╔══██╗████╗ ████║████╗  ██║██║██╔════╝
███████║██╔████╔██║██╔██╗ ██║██║███████╗
██╔══██║██║╚██╔╝██║██║╚██╗██║██║╚════██║
██║  ██║██║ ╚═╝ ██║██║ ╚████║██║███████║
╚═╝  ╚═╝╚═╝     ╚═╝╚═╝  ╚═══╝╚═╝╚══════╝
----------------------------------------
Java like Streams Api for PythonStreams are lazy evaluated -- That is, evaluation starts only when a terminal operation is appliedInstallationpip install this repo.
(Note: Incompatible with Python 2.x)pip3installamnis(or)pipinstallamnisUsage examplesallmatchCheck if all elements in the stream match a condition.This method returnsTrueif all elements in the stream satisfy the condition
defined by the provided functionfn. If any element does not satisfy the
condition,Falseis returned.fromamnisimportStreamresult=(Stream(["cat","fat","rat"]).allmatch(lambdax:"at"inx))# Trueresult=(Stream(["cat","dog","rat"]).allmatch(lambdax:"at"inx))# FalseanymatchCheck if any element in the stream matches a condition.This method returnsTrueif at least one element in the stream satisfies the
condition defined by the provided functionfn. If no element satisfies the
condition,Falseis returned.fromamnisimportStreamresult=(Stream(["cat","dog","rat"]).anymatch(lambdax:"at"inx))# Trueresult=(Stream(["cat","dog","rat"]).anymatch(lambdax:"z"inx))# FalsecatchHandle exceptions while iterating through the stream.This method returns a new Stream that applies the provided exception handler
functionhandlerto handle exceptions of a specific typeerr_typewhile
iterating through the stream. The handler can return a value to continue
iteration, or raise a different exception to propagate it.# =======# Logging# =======fromamnisimportStreamimportloggingdefhandler(err):logging.error(err)result=(Stream(['a','b','c',10,'d']).map(lambdax:x.upper()).catch(handler).collect(list))# >>> ERROR:root:'int' object has no attribute 'upper'# result = ['A', 'B', 'C', None, 'D']# =======================# Multiple Error Handling# =======================fromamnisimportStreamimportloggingdefhandle_upper(err):logging.error(err)defhandle_index_out_of_bounds(err):logging.warning(err)result=(Stream(['ab','cd','e',10,'fg']).map(lambdax:x.upper()).catch(handle_upper).map(lambdax:x[1]).catch(handle_index_out_of_bounds).collect(list))# >>> WARNING:root:string index out of range# >>> ERROR:root:'int' object has no attribute 'upper'# result = ['B', 'D', 'G']# ===================# Replace Error Value# ===================fromamnisimportStreamdefsqrt(x):ifx<0:raiseValueError(x)returnx**0.5defhandler_neg_sqrt(err):(value,)=err.argsreturnvalue*1000result=(Stream([4,9,-3,16]).map(sqrt).catch(handler_neg_sqrt).collect(list))# [2.0, 3.0, -3000, 4.0]# =======================# Specific Error Handling# =======================deferr_fn(x):ifx=='a':raiseValueError(x)ifx=='b':raiseKeyError(x)returnxdefhandle_value_err(err):(value,)=err.argsreturnvalue*2defhandle_key_err(err):(value,)=err.argsreturnvalue*4result=(Stream(['e','a','g','d','b']).map(err_fn).catch(handle_value_err,ValueError).catch(handle_key_err,KeyError).collect(list))# ['e', 'aa', 'g', 'd', 'bbbb']collectCollect the elements in the stream into a collection.This method collects the elements in the stream and returns them as a collection,
determined by the provided collector function. The default collector isiter,
which returns an iterable containing the elements.fromamnisimportStreamresult=Stream([1,2,3]).collect(list)# [1, 2, 3]countCount the number of elements in the stream.This method returns the total number of elements in the stream.fromamnisimportStreamresult=Stream(['a','b','c']).count()# 3distinctRemove duplicate elements from the stream.This method returns a new Stream containing only the distinct elements from the
original stream. Duplicate elements are eliminated, and only the first occurrence
is retained.fromamnisimportStreamresult=(Stream([3,2,3,1,3,2,2]).distinct().collect(list))# [3, 2, 1]filterFilter elements in the stream based on a given condition.This method filters the elements in the stream, retaining only those that satisfy
the provided condition defined by the functionfn.fromamnisimportStreamresult=(Stream([1,2,3]).filter(lambdax:x>1).collect(list))# [2, 3]findFind the first element that matches a condition in the stream.This method returns the first element from the stream that satisfies the condition
defined by the provided functionfn. If no matching element is found,Noneis returned.fromamnisimportStreamresult=Stream([5,4,3,2,1]).find(lambdax:x%2==0)# 4firstGet the first element from the stream.This method returns the first element from the stream, orNoneif the stream is empty.fromamnisimportStreamresult=Stream([1,2,3]).first()# 1flatmapApply a function to each element and flatten the results into a single stream.This method applies the provided functionfnto each element in the stream and
then flattens the resulting iterable of each function call into a single stream.flatmap is exactly the same as doing map and flattenfromamnisimportStreamresult=(Stream(["it's Sunny in","","California"]).flatmap(lambdas:s.split(" ")).collect(list))# ["it's", "Sunny", "in", "", "California"]flattenFlatten a stream of nested iterables into a single stream.This method flattens a stream that contains nested iterables, such as lists or
tuples, into a single stream of individual elements.fromamnisimportStreamresult=(Stream([[1,2,3],[],[4,5]]).flatten().collect(list))# [1, 2, 3, 4, 5]foreachApply a function to each element in the stream.This method applies the provided functionfnto each element in the stream.
The function can have side effects.fromamnisimportStreamStream([1,2,3]).foreach(lambdax:print(x))# >>> 1# >>> 2# >>> 3groupGroup elements in the stream based on keys and values.This method groups elements in the stream based on keys and values determined by
the provided key and value functions. The grouping logic is defined by the provided
grouper object, which specifies how values are combined for each key.Parameters:key_fn: A function that takes an element of typeTand
returns a key of typeUto group the elements by.val_fn: A function that takes an element of typeTand
returns a value of typeVassociated with the element.grouper: A Grouper object that specifies how values are combined for each key.
The Grouper should havecollectionandgrouper_fnattributes.Returns:
dict: A dictionary where keys are the result of the key function and values
are the results of applying the grouper function to the associated values.fromamnisimportStream,Grouperresult=(Stream(["apple","banana","cherry"]).group(key_fn=lambdaword:len(word),val_fn=lambdaword:word.upper(),grouper=Grouper(list,grouper_fn=lambdal,item:l.append(item))))# {5: ['APPLE'], 6: ['BANANA', 'CHERRY']}classPerson:def__init__(self,name,age):self.name,self.age=name,agepeople=[Person("jack",20),Person("jack",30),Person("jill",25),Person("jack",40)]result=(Stream(people).group(key_fn=lambdap:p.name,val_fn=lambdap:p.age,grouper=Grouper(list,grouper_fn=lambdal,item:l.append(item))))# {#   "jack": [20, 30, 40],#   "jill": [25]# }result=(Stream(people).group(key_fn=lambdap:p.name,val_fn=lambdap:p.age,grouper=Grouper(str,grouper_fn=lambdas,item:f"{s}--{item}"ifselsef"{item}")))# {#   "jack": "20--30--40",#   "jill": "25"# }inspectApply a function to each element in the stream while preserving the stream's contents.This method returns a new Stream that applies the provided functionfnto each
element in the original stream. The function is called for every element, and it can
have side effects. The original elements remain unchanged, and the new Stream still
contains the same elements.fromamnisimportStreamresult=(Stream([1,2,3]).inspect(lambdax:print(f"before map :{x}")).map(lambdax:x*3).inspect(lambdax:print(f"after map  :{x}")).collect(list))# >>> before map : 1# >>> after map  : 3# >>> before map : 2# >>> after map  : 6# >>> before map : 3# >>> after map  : 9# result = [3, 6, 9]lastGet the last element from the stream.This method returns the last element from the stream, orNoneif the stream is empty.fromamnisimportStreamresult=Stream([1,2,3]).last()# 3limitLimit the number of elements in the stream.This method returns a new Stream containing, at most, the firstnelements from
the original stream. Ifnis greater than the total number of elements, all
elements from the original stream will be included.fromamnisimportStreamresult=(Stream(range(100)).limit(10).collect(list))# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]mapApply a function to each element in the stream.This method applies the provided functionfnto each element in the stream
and returns a new Stream containing the transformed values.fromamnisimportStreamresult=(Stream([1,2,3]).map(lambdax:x*2).collect(list))# [2, 4, 6]maxFind the maximum element in the stream.This method returns the maximum element from the stream, based on the natural
ordering of the elements or a custom sorting key defined by thekeyparameter.fromamnisimportStreamresult=Stream(["a","bbbbb","cc"]).max()# "cc"result=Stream(["a","bbbbb","cc"]).max(lambdax:len(x))# "bbbbb"minFind the minimum element in the stream.This method returns the minimum element from the stream, based on the natural
ordering of the elements or a custom sorting key defined by thekeyparameter.fromamnisimportStreamresult=Stream(["cc","aaaaa","b"]).min()# "aaaaa"result=Stream(["cc","aaaaa","b"]).min(lambdax:len(x))# "b"nomatchCheck if no elements in the stream match a condition.This method returnsTrueif none of the elements in the stream satisfy the condition
defined by the provided functionfn. If any element satisfies the condition,Falseis returned.fromamnisimportStreamresult=(Stream([3,5,7]).nomatch(lambdax:x%2==0))# Trueresult=(Stream([3,4,7]).nomatch(lambdax:x%2==0))# FalsenthGet the element at the nth position in the stream.This method returns the element at the specified positionnin the stream. If the
position is out of bounds,Noneis returned. The position index is zero-based.
Negative indexes are not supported.fromamnisimportStreamresult=Stream([1,2,3]).nth(1)# 2par_mapParallel version of themapmethod for CPU-bound operations.
The results may not be in the same order as the original stream due
to the parallel execution.IMPORTANT: Lambda functions are not allowed asfnsince they are not easily
serializable for parallel execution. Define your mapping function as a regular
named function.See the documentation for themapmethod for more details.fromamnisimportStreamdeftimes2(x):returnx*2result=(Stream([1,2,3]).par_map(times2).collect(list))# [2, 4, 6]reduceReduce the elements in the stream to a single value.This method applies the provided binary functionfncumulatively to the elements
of the stream, from left to right, and returns a single accumulated result. An
initial value can be provided to start the accumulation; otherwise, the first element
of the stream is used as the initial value.fromamnisimportStreamresult=(Stream([1,2,3]).reduce(lambdax,y:x+y))# 6importoperatorresult=(Stream([1,2,3]).reduce(operator.add,initial=20))# 26skipSkip the firstnelements in the stream.This method returns a new Stream containing the elements from the original stream
after skipping the firstnelements. Ifnis greater than the total number of
elements, an empty stream will be returned.Stream([1, 2, 3]).skip(2)fromamnisimportStreamresult=(Stream([1,2,3]).skip(2).collect(list))# [3]skipwhileCreate a new stream by skipping elements while a condition is met.This method returns a new Stream that starts including elements from the original
stream as soon as the provided condition defined by the functionfnevaluates to False.
Elements before the first one that does not satisfy the condition are skipped.fromamnisimportStreamresult=(Stream([1,2,2,3,5,3,2,3,5]).skipwhile(lambdax:x<3).collect(list))# [3, 5, 3, 2, 3, 5]sortedSort the elements in the stream.This method returns a new Stream containing the elements from the original stream,
sorted in ascending order by default. A custom sorting key can be provided using
thekeyparameter.WARNING: Sorting is an eager operation and requires all elements to be loaded into memory.fromamnisimportStreamresult=(Stream([5,4,3,2,1]).sorted().collect(list))# [1, 2, 3, 4, 5]result=(Stream([(1,4),(2,3),(3,2),(4,1)]).sorted(key=lambdap:p[1]).collect(list))# [(4, 1), (3, 2), (2, 3), (1, 4)]takewhileCreate a new stream with elements while a condition is met.This method returns a new Stream that includes elements from the original stream
as long as the provided condition defined by the functionfnevaluates to True.
Once an element is encountered that does not satisfy the condition, the new stream
stops including further elements.fromamnisimportStreamresult=(Stream([1,2,2,4,5,3,2,3,5]).takewhile(lambdax:x<5).collect(list))# [1, 2, 2, 4]windowCreate a sliding window over the stream.This method returns a new Stream where each element is a tuple containing the elements
of the original stream that form a sliding window of the specified sizewindow_size.
The elements within each window are ordered as they appear in the stream.fromamnisimportStreamresult=(Stream([1,2,3,4,5]).window(3).collect(list))# [#     (1, 2, 3),#     (2, 3, 4),#     (3, 4, 5),# ]result=(Stream([1,2,3,4,5]).window(3).map(lambdaw:w[0]+w[1]+w[2]).collect(list))# [6, 9, 12]Development setupClone this repo and install packages listed in requirements.txtpip3install-rrequirements.txtMetaM. Zahash -zahash.z@gmail.comDistributed under the MIT license. SeeLICENSEfor more information.https://github.com/zahash/ContributingFork it (https://github.com/zahash/amnis/fork)Create your feature branch (git checkout -b feature/fooBar)Commit your changes (git commit -am 'Add some fooBar')Push to the branch (git push origin feature/fooBar)Create a new Pull Request