Package: py3streams
py3streams - manipulate collectionsPackage contains classes to support operations on collections and container object to control data flow.Stream,IntStream,DictStreammanipulate lists, tuples, dicts, ranges and other streams with chain of generators.Optionalobject is a container which can hold other object. With defined methodsOptionalhelps manage the object and control flow if its exists or not, return default value in case of None or empty, or execute lambda function using stored object if stored object exists (if_present(lambda)).Table of contentsDescriptionInstallationUsage[Build-in functions](#Build-in functions)DescriptionClasses from the package are:Stream,IntStreamandDictStream. Classes may help with manipulate nested lists or dicts, filter values with build-in object functions or map functions on the values. There are few cases which is very important to understand:classes are not collections but they are iterable,methods which manipulate values (filter,map,fmap) are stored in chain of generators and wait for invoke,Streams cannot be reused and stored chain of generators can be evaluated only once,Streams are invoked during iteration withfor-loopor with methods which build collection from them (to_list(),to_dict()), evaluate if any value match something (any_match()orall_match()) or checksum(),count(),max()etc.Optionalobject is a container which may hold value (any other object) and helps with manipulate it.get()method fromOptionalobject will return stored value.get_or_else(default)will return if stored value is not None and exists, otherwise return default,is_present()allows check if stored data is not None and exists,if_present(lambda)executes lambda function on stored data if its exists. Method will return result from lambda, or None if nothing was executed.For example theOptionalobject is returned duringStreamoperation with method:get_first().Lets define example list which will be used in few next examples:from py3streams import Stream

example_list = ["1", "5", 2, "10", 11]Example: sum values from collection.sum = Stream(example_list).map(lambda x: int(x)).filter(lambda x: x < 10).sum()
# result: [1, 5, 2] -> 8Alternative behaviour with build-in Stream's methods:sum = Stream(example_list).map_to_int().lt(10).sum()In the example classStreamhas been used on theexample_list. First there is registered generator for changing strings to ints, then registered generator with lambda expression for elements lower than10and sum them.Streams can be used withfor-loop:for i in Stream(example_list).map_to_int().lt(10).sum():
    print(i)
# results are 1, 5 and 2.InstallatonTo use the streams install the package.pip3 install py3streamsUsageStreams help manipulate collections. For most actions its enough to use filter(), map() and fmap() methods.
Classes contain build-in functions which include lambdas and allow use short-name methods for similar result.Example 1: filter elements.Lets define a list:elements = [0, 1, "2", 3, None, [5, 6, "7"], ["8"]]Stream will find elements lower than 3. Sub-lists and None values should be ignored.stream = Stream(elements).filter(lambda x: x is not None).filter(lambda x: not isinstance(x, list)).map(lambda x: int(x)).filter(lambda x: x < 3) # still we have a stream 
for e in stream:
    print(e)
# result 0, 1 and 2and alternative with Stream's functions:stream = Stream(elements).no_list().no_none().map_to_int().lt(3)
for e in stream:
    print(e)
# result 0, 1 and 2Example 2: get_first() withOptionalobject.Lets define a list:elements = ["a", "b", 3, 4]Stream will find first int.opt = Stream(elements).filter(lambda x: isinstance(x, int)).get_first()
# opt is an Optional object with stored value=3.
print(opt.get())
# print-out: 3get_first(default_value=None)returns None if Stream does not find element by default.opt = Stream(elements).filter(lambda x: isinstance(x, list)).get_first()
# opt is an Optional object. Value does not exists in Stream after apply filters. Stored value in Optional Object is **None**.
print(opt.get_or_else("another-value"))
# print-out: another-valuefor short example, lets apply lambda function with print() if value exists.Stream(elements).filter(lambda x: isinstance(x, list)).get_first().if_present(lambda x: print(x))
# result: nothing will be printed, because stream does not have elements after filter applyExample 3: in-line nested lists withfmap()Lets define a list:elements = [[1,2,3], [4], "val1", "val2", [5,6,7]]Filter list elements and merge them.nested_elements = Stream(elements).filter(lambda x: isinstance(x, list)).fmap(lambda x: Stream(x)).to_list()
# result: [1,2,3,4,5,6,7]Build-in functionsLambda mechanism can be replaced with few build-in methods which contains lambdas inside and hide them from the user.
Alternatives workonlywithStreamclass.classic filter/mapbuild-in alternativeCommentsmap(lambda x: str(x))map_to_str()change elements to strmap(lambda x: int(x))map_to_int()change elements to intmap(lambda x: float(x))map_to_float()change elements to floatfilter(lambda x: isinstance(x, dict))only_dict()select only dictsfilter(lambda x: isinstance(x, (list, set, tuple)))only_list()select only listsfilter(lambda x: not isinstance(x, (list, set, tuple)))no_list()select all except listsfilter(lambda x: x is not None)no_none()select all (includes zeros, empty string:"" and empty lists:[]) except Nonefilter(lambda x: x)exists()elements which exists and are not emptyfilter(lambda x: x%2 == 0)even()even numbersfilter(lambda x: (x%2 - 1) == 0)odd()odd numbersfilter(lambda x: x > value)gt(value: int)greater thanfilter(lambda x: x < value)lt(value: int)less thanfilter(lambda x: x >= value)ge(value: int)greater and equalfilter(lambda x: x <= value)le(value: int)less and equalfilter(lambda x: x == value)eq(value: object)equal to