2009-03-09 38 views
34

IronPythonでLINQの型と拡張メソッドを使用することはできますか?IronPythonでLINQタイプと拡張メソッドを使用できますか?

もしそうなら、そして、同じことをするために、より多くの場合は、非常にpythonicですか?

+0

Ólafur、Steve Gilhamの答えを選択して、この質問にアクセスしたユーザーが最新の正しい情報を参照してください。 50Kでは、私はジョン・フェミネラがその代表を欠場するとは思わない。 –

答えて

41

IronPython 2.7は、このギャップを最終的にネームスペースからターゲットタイプに拡張メソッドを追加するclr.ImportExtensionsメソッドと橋渡しします。

>& '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__'] 
>>> 

これは、IronRuby 1.1のusing_clr_extensionsメソッドに対応しています。

23

あなたがLINQをどうしたいもののいくつかは、リストの内包表記を行うことができます。

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

それとも、マップを使用削減、およびフィルタすることができます

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

しかし、リストの内包があります関数型プログラミング構造体を使用するよりもはるかに「Python型」です。物を減らすために、"" .joinまたはの合計を使用することを検討してください。

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

そして、あなたはあなたの方法にもなります。そして、あなたはただ、これらの翻訳を覚えて任意のすべて

を使用することによって全体イテラブルの真の値を確認することができます!

+3

また、set()はDistinct()の代わりになります。 – Phil

3

I described a C# wrapper class LINQ拡張メソッドを使用して、IronPythonのC#の「チェーン拡張メソッド」構文と似た構文を実現します。

考え方は、単に拡張メソッドを呼び出すIEnumerableの周りの一種のデコレータクラスを持つことです。

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

免責事項:これは、次のような構文が可能になります:-)

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, ... 

} 

おそらく、このラッパークラスは、IronPythonのにちょうど同様に書き込むことができますが、私はまだのpythonのように流暢ではありませんよこれは私が学習教材として試したことですが、実際のプロジェクトではこれを使用していません。

11

IronPython 2.7.1このユースケースの場合、clr.ImportExtensionsがあります。

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) 

少し背景:IronPython 2.7が最初にこの機能が導入されましたが、実際に使用可能であることから、それを停止しan issueがありました。