È 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?
È 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?
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.
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!
anche, set() è un buon sostituto di Distinct() – Phil
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.
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.
Ó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. –