Package: leopards
LeopardsLeopards is a way to query list of dictionaries or objects as if you are filtering in  DBMS.
You can get dicts/objects that are matched by OR, AND or NOT or all of them.
As you can see in the comparison they are much faster than Pandas.InstallationpipinstallleopardsUsagefromleopardsimportQl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"}]filtered=Q(l,{'name__contains':"k","age__lt":20})print(list(filtered))output[{'name':'Mike','age':'19'}]The above filtration can be written asfromleopardsimportQl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"}]filtered=Q(l,name__contains="k",age__lt=20)Notes:Qreturns an iterator which can be converted to a list by callinglist.Even though, age wasstrin the dict, as the value of in the query dict wasint, Leopards converted the value in dict automatically to match the query data type. This behaviour can be stopped by passingFalsetoconvert_typesparameter.Supported filterseq: equals and this default filtergt: greater than.gte: greater than or equal.lt: less thanlte: less than or equalin: the value in a list of a tuple.e.g.  age__in=[10,20,30]contains: contains a substring as in the example.icontains: case-insensitivecontains.startswith: checks if a value starts with a query strings.istartswith: case-insensitivestartswith.endswith: checks if a value ends with a query strings.iendswith: case-insensitiveendswith.isnull:  checks if the value matches any of NULL_VALUES which are('', '.', None, "None", "null", "NULL")e.g.filter__isnull=Trueorfilter__isnull=FalseForeq,gt,gte,lt,lte,in,contains,icontains,startswith,istartswith,endswithandiendswith, you can add anto negate the results. e.gninwhich is equivalent tonot inAdvanced examplesThis section will cover the use ofOR,ANDandNOTUsage ofORORor__or__takes a list of dictionaries to evaluate and returns with the firstTrue.fromleopardsimportQl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"}]filtered=Q(l,{"OR":[{"name__contains":"k"},{"age__gte":21}]})print(list(filtered))output[{'name':'Mike','age':'19'},{'name':'Sarah','age':'21'}]Usage ofNOTNOTor__not__takes a dict for query run.fromleopardsimportQl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"}]filtered=Q(l,{"age__gt":15,"NOT":{"age__eq":19}})print(list(filtered))output[{'name':'John','age':'16'},{'name':'Sarah','age':'21'}]Usage ofANDANDor__and__takes a list of dict for query run, returns with the firstFalse.fromleopardsimportQl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"}]filtered=Q(l,{"__and__":[{"age__gte":15},{"age__lt":21}]})print(list(filtered))output[{'name':'John','age':'16'},{'name':'Mike','age':'19'}]Aggregating DataYou  can run the following aggregationsCountMaxMinSumAvgCountFind the count of certain aggregated columnl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"},{"name":"John","age":"19"}]fromleopardsimportCountcount=Count(l,['age'])output[{"age":"16","count":1},{"age":"19","count":2},{"age":"21","count":1}]MaxFind the Max value for a certain column in  certain aggregated columnsl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"},{"name":"Joh","age":"19"}]fromleopardsimportMaxcount=Max(l,"age",['name'],dtype=int)output[{'name':'John','age':'19'},{'name':'Mike','age':'19'},{'name':'Sarah','age':'21'}]Notes:If you don't pass the aggregation columns, the maximum will be found across dataset.You can pass the datatype of the column to convert it on the fly while evaluatingl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"},{"name":"Joh","age":"19"}]fromleopardsimportMaxm=Max(l,"age",dtype=int)output[{'age':21}]MinFind the Max value for a certain column in  certain aggregated columnsl=[{"name":"John","age":"16"},{"name":"Mike","age":"19"},{"name":"Sarah","age":"21"},{"name":"Joh","age":"19"}]fromleopardsimportMinm=Min(l,"age",['name'])output[{'name':'John','age':'16'},{'name':'Mike','age':'19'},{'name':'Sarah','age':'21'}]Note:If you don't pass the aggregation columns, the min will be found across dataset.You can pass the datatype of the column to convert it on the fly while evaluatingSum and AvgLike Min and Max but only works with integers and floats.Comparison with PandasThis is done on Python 3.8 running on Ubuntu 22.04 on i7 11th generation and 32 GB of RAM.ComparisonPandasLeopardsPackage Size(Lower is better)29.8 MB7.5 KBimport Time (Worst)(Lower is better)146 ms1.05 msload 10k CSV lines(Lower is better)[1]0.295s0.138sget first matched record(Lower is better)0.310s0.017sprint all filtered records (10/10k)(Lower is better)0.310s0.137sfilter by integers(Lower is better)0.316s0.138s[1]This was loading the whole csv in memory which was for sake of fair comparison.
Nevertheless,  Leopards can work with DictReader as an iterable which executes in0.014s, then it handles line by line.Thanks forAsma Tahirfor Pandas stats.TutorialsWork on CSV Files with Leopards