2009-03-09 9 views
34

È possibile utilizzare i tipi LINQ e i metodi di estensione in IronPython?È possibile utilizzare i tipi LINQ e i metodi di estensione in IronPython?

Se sì, come? E c'è anche spesso più pitonico per fare la stessa cosa?

+0

Ólafur, selezionare la risposta di Steve Gilham in modo che le persone che accedono a questa domanda visualizzino informazioni corrette aggiornate. A 50K, non credo che John Feminella salterà la replica. –

risposta

41

IronPython 2.7 alla fine colma questo divario con il metodo clr.ImportExtensions che aggiunge i metodi di estensione da uno spazio dei nomi ai tipi di destinazione, ad es.

>& 'C:\Program Files\IronPython 2.7\ipy.exe' 
IronPython 2.7 (2.7.0.40) on .NET 4.0.30319.225 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import clr 
>>> clr.AddReference("System.Core") 
>>> from System.Collections.Generic import List 
>>> dir (List) 
['Add', 'AddRange', 'AsReadOnly', 'BinarySearch', 'Capacity', 'Clear', 'Contains', 'ConvertAll', 'CopyTo', 'Count', 'Enu 
merator', 'Equals', 'Exists', 'Find', 'FindAll', 'FindIndex', 'FindLast', 'FindLastIndex', 'ForEach', 'GetEnumerator', ' 
GetHashCode', 'GetRange', 'GetType', 'IndexOf', 'Insert', 'InsertRange', 'IsReadOnly', 'IsSynchronized', 'Item', 'LastIn 
dexOf', 'MemberwiseClone', 'ReferenceEquals', 'Remove', 'RemoveAll', 'RemoveAt', 'RemoveRange', 'Reverse', 'Sort', 'Sync 
Root', 'ToArray', 'ToString', 'TrimExcess', 'TrueForAll', '__add__', '__class__', '__contains__', '__delattr__', '__doc_ 
_', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce 
__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__'] 
>>> import System 
>>> clr.ImportExtensions(System.Linq) 
>>> dir (List) 
['Add', 'AddRange', 'Aggregate', 'All', 'Any', 'AsEnumerable', 'AsParallel', 'AsQueryable', 'AsReadOnly', 'Average', 'Bi 
narySearch', 'Capacity', 'Cast', 'Clear', 'Concat', 'Contains', 'ConvertAll', 'CopyTo', 'Count', 'DefaultIfEmpty', 'Dist 
inct', 'ElementAt', 'ElementAtOrDefault', 'Enumerator', 'Equals', 'Except', 'Exists', 'Find', 'FindAll', 'FindIndex', 'F 
indLast', 'FindLastIndex', 'First', 'FirstOrDefault', 'ForEach', 'GetEnumerator', 'GetHashCode', 'GetRange', 'GetType', 
'GroupBy', 'GroupJoin', 'IndexOf', 'Insert', 'InsertRange', 'Intersect', 'IsReadOnly', 'IsSynchronized', 'Item', 'Join', 
'Last', 'LastIndexOf', 'LastOrDefault', 'LongCount', 'Max', 'MemberwiseClone', 'Min', 'OfType', 'OrderBy', 'OrderByDesc 
ending', 'ReferenceEquals', 'Remove', 'RemoveAll', 'RemoveAt', 'RemoveRange', 'Reverse', 'Select', 'SelectMany', 'Sequen 
ceEqual', 'Single', 'SingleOrDefault', 'Skip', 'SkipWhile', 'Sort', 'Sum', 'SyncRoot', 'Take', 'TakeWhile', 'ToArray', ' 
ToDictionary', 'ToList', 'ToLookup', 'ToString', 'TrimExcess', 'TrueForAll', 'Union', 'Where', 'Zip', '__add__', '__clas 
s__', '__contains__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', 
'__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__' 
, '__str__', '__subclasshook__'] 
>>> 

che pone in linea con il metodo using_clr_extensions IronRuby 1.1 di.

23

Alcune delle cose che faresti con LINQ può essere fatto con list comprehension:

[myFunc(i) for i in numbers if i > 3] 

oppure è possibile utilizzare carta, ridurre, e di filtro:

map(myFunc, filter(lambda x: x > 3, numbers)) 

Ma list comprehension sono molto più "Pythonic" rispetto all'uso dei costrutti di programmazione funzionale. Per ridurre le cose, considerare l'utilizzo di "" .join o somma. E si può controllare il valore di verità di intere iterables utilizzando qualsiasi e tutto

Basta ricordare queste traduzioni:

Select -> map 
Where -> filter 
Aggregate -> reduce 

e sarete sulla buona strada!

+3

anche, set() è un buon sostituto di Distinct() – Phil

3

I described a C# wrapper class attorno ai metodi di estensione LINQ per ottenere una sintassi simile alla sintassi del metodo di estensione concatenata di C# in IronPython.

L'idea è di avere una sorta di classe decoratore intorno a IEnumerable che chiama semplicemente i metodi di estensione. Probabilmente questo classe wrapper può essere scritto altrettanto bene in IronPython, ma io non sono come fluente in pitone ancora :-)

public class ToLinq<T> : IEnumerable<T> 
{ 
    private readonly IEnumerable<T> _wrapped; 

    public ToLinq(IEnumerable<T> wrapped) 
    { 
     _wrapped = wrapped; 
    } 

    public ToLinq<T> Where(Func<T, bool> predicate) 
    { 
     return new ToLinq<T>(_wrapped.Where(predicate)); 
    } 


    // ... similar methods for other operators like Select, Count, Any, ... 

} 

Ciò consente una sintassi simile a questa:

johns = ToLinq[Customer](customers)\ 
      .Where(lambda c: c.Name.StartsWith("John"))\ 
      .Select(lambda c: c.Name) 

di responsabilità : questo è qualcosa che ho provato come esercizio di apprendimento, non l'ho usato in un progetto del mondo reale.

11

In IronPython 2.7.1 si dispone di clr.ImportExtensions per questo caso d'uso.

import clr 
clr.AddReference("System.Core") 
import System 
clr.ImportExtensions(System.Linq) 

# will print 3 and 4 :) 
[2, 3, 4].Where(lambda x: x != 2).ToList().ForEach(System.Console.WriteLine) 

Un po 'di storia: IronPython 2.7 inizialmente introdotto questa caratteristica, ma c'era an issue che si è fermato di essere realmente utilizzabile.