pip install -U linq-t
- Typed-Linq = Linq + Static Checking(PyCharm performs best)
- Linq = Auto-Completion + Readability
- Static Checking = Safety + Debugging when coding
Additionally, static checking helps to type inference which improves the auto-completion.
Here is an example to get top 10 frequent pixels in a picture.
fromlinqimportFlowimportnumpyasnpdefmost_frequent(arr: np.ndarray) ->np.ndarray:
returnFlow(arr.flatten()) \
.group_by(None) \
.map(lambdak, v: (k, len(v))) \
.sorted(by=lambdak, count: -count)\
.take(10) \
.map(lambdak, v: k) \
.to_list() \
.then(np.array)
._# unboxThe well-known EDSL in .NET, Language Integrated Query, in my opinion, is one of the best design in .NET environment.
Here is an example of C# Linq.
// Calculate MSE loss./// <param name="Prediction"> the prediction of the neuron network</param>/// <param name="Expected"> the expected target of the neuron network</param>Prediction.Zip(Expected,(pred,expected)=>Math.Square(pred-expected)).Average()It's so human readable and it doesn't cost much.
Reference:
- Microsoft .NET general introduction => LINQ: .NET Language-Integrated Query.
- Wikipedia => Language Integrated Query.
And there are so many scenes very awkward to Python programmer, using Linq might help a lot.
seq1=range(100)
seq2=range(100, 200)
zipped=zip(seq1, seq2)
mapped=map(lambdaab: ab[0] /ab[1], zipped)
grouped=dict()
group_fn=lambdax: x//0.2foreinmapped:
group_id=group_fn(e)
ifgroup_idnotingrouped:
grouped[group_id] = [e]
continuegrouped[group_id].append(e)
foreingrouped.items():
print(e)The codes seems to be too long...
Now we extract the function group_by:
defgroup_by(f, container):
grouped=dict()
foreincontainer:
group_id=f(e)
ifgroup_idnotingrouped:
grouped[group_id] = [e]
continuegrouped[group_id].append(e)
returngroupedres=group_by(lambdax: x//0.2, map(lambdaab[0]/ab[1], zip(seq1, seq2)))Okay, it's not at fault, however, it makes me upset —— why do I have to write these ugly codes?
Now, let us try Linq!
fromlinqimportFlow, extension_stdseq=Flow(range(100))
res=seq.zip(range(100, 200)).map(lambdafst, snd : fst/snd).group_by(lambdanum: num//0.2)._How does Linq.py work?
There is a core class object, linq.core.flow.TSource, which just has one member _.
When you want to get a specific extension method from TSource object,
the type of its _ member will be used to search whether the extension method exists.
In other words, extension methods are binded with the type of _.
classTSource:
__slots__= ['_']
def__init__(self, sequence):
self._=sequencedef__getattr__(self, k):
forclsinself._.__class__.__mro__:
namespace=Extension.get(cls, '')
ifkinnamespace:
returnpartial(namespace[k], self)
where=','.join('{}.{}'.format(cls.__module__, cls.__name__) forclsinself._.__class__.__mro__)
raiseNameError("No extension method named `{}` for types `{}`.".format(k, where))
def__str__(self):
returnself._.__str__()
def__repr__(self):
returnself._.__repr__()
classFlow(Generic[T]):
def__new__(cls, seq):
returnTSource(seq)Here are two methods for you to do so.
you can use
extension_stdto add extension methods for all Flow objects.you use
extension_class(cls)to add extension methods for all Flow objects whose member_'s type iscls.
@extension_std# For all Flow objectsdefAdd(self, i):
returnself+i@extension_class(int) # Just for type `int`defAdd(self: int, i):
returnself+iassertFlow(4).add(2)._is6Note: Docs haven't been finished yet.
Index
Design the standard library for Linq.py.
Write documents for the standard library and tutorials about how to use Linq.py.
Join LinqPy Room to discuss about any aspects of Linq.py.
Feel free to pull requests here.