2

以下の私の質問に不可欠な次のコードを検討してください。

import functools

N = 3

class Struct:
    """Create an instance with argument=value slots.
    This is for making a lightweight object whose class doesn't matter."""
    def __init__(self, **entries):
        self.__dict__.update(entries)

    def __repr__(self):

        args = ['%s=%s' % (k, repr(v)) for (k, v) in vars(self).items()]
        return '\nStruct(%s)' % ', '.join(args)

def doit( move ):

    ( rowIn, colIn ) = move
    something = rowIn  + ( 10 * colIn ) # An involved computation here in real life

    return Struct( coord = ( rowIn, colIn ), something = something )

legalStates = [ ( row, col ) for row in xrange( N ) for col in xrange( N ) ] # A more complicated function that generates the list in real life. Call it 'complicatedFunction'

genExpFn = lambda : ( ( s.something, m, s ) for ( m, s ) in ( ( move, doit( move ) ) for move in legalStates ) )  #Q1

successorsSortedGenFn = lambda : ( p for p in sorted( genExpFn(), reverse = True ) )

def bFunc( s, a ):

    #print "a * s ->", a * s
    return a * s # An involved computation here in real life

def aFunc( ( v, m, s ) ): #Q2

    assert( s.something == v )
    return bFunc( s.something, 10 )

print "min( successorsSortedGen ) -> " + str( min( successorsSortedGenFn(), key=functools.partial( aFunc )) ) #Q3
print
print "max( successorsSortedGen ) -> " + str( max( successorsSortedGenFn(), key=functools.partial( aFunc )) ) #Q4

私の質問は、「#Q」とマークされたステートメントに基づいています。

Q1sorted() :ジェネレーターを呼び出すと(すべての要素が生成され、ソートされて新しいリストとして返される一時的なソートされていないリストが作成されます)、ジェネレーターが完全にインスタンス化されている(すべての要素が実行されている)ことは明らかです。

一時的なものの作成を最小限に抑え、ソートされたリストを生成する、スペース効率の良い方法はありますか?

しようとしましたが、を使用して適切に並べ替えることができるリスト内包表記を記述できませんでしたlist.sort()

これは私が考えていた種類の表現でした:

successorsSorted = [ ( s.something, m, s ) for ( m, s ) in ( ( move, doit( move ) ) for move in legalStates ) ].sort( reverse = True )

Q2:呼び出しで同等の表現を記述できなかったため、「aFunc」は「bFunc」の単なるラッパーであることに注意してくださいfunctools.partial( aFunc )

「bFunc」を直接呼び出すことができる表現「aFunc」とは何functools.partial( aFunc )ですか?


編集:Q2への答えはlambda ( v, m, s ): bFunc(s.something, 10)

したがって、ステートメントは次のようになります。

print "min( successorsSortedGen ) -> " + str( min( successorsSortedGenFn(), key=functools.partial( lambda ( v, m, s ): bFunc(s.something, 10)) ) )
print
print "max( successorsSortedGen ) -> " + str( max( successorsSortedGenFn(), key=functools.partial( lambda ( v, m, s ): bFunc(s.something, 10)) ) )

私はそれがちょっと足りないように見えることを知っています、私はこれについて以前は考えていませんでしたが、まあ(穏やかなproddingのためのaaronasterlingのおかげで)。


Q3、Q4:min()とmax()に渡される要素はすでにソートされていることに注意してください。

このヒントをmin()とmax()に作成して、リスト全体を一時的なものとしてインスタンス化してから、リスト全体を反復処理してminまたはmax要素を見つけないようにすることはできますか?

そうでない場合、リスト全体をインスタンス化しないモジュールまたはカスタム関数が存在しますが、渡されたリストがソートされている場合、最小数の要素を検査しながら最小要素または最大要素を返しますか?

4

1 に答える 1

2

Q1。[x for x in somelist].sort()リストを作成し、メソッドを呼び出しますsort。これにより、割り当てがにNone割り当てNoneられsuccessorSortedます。これを実行したい場合は、自分で実装する必要があり、一時リストを作成する組み込みのソートよりもかなり遅くなる可能性があります。

Q2。コードオブジェクトを分解し、それが最初の引数になるように引数リストを再配置してaから、ローカルの新しい位置を考慮してすべてのバイトコードを書き直すことができます。(はい、これは実際に行うことができます)。その後、その上で使用できますfunctools.partial。または、現在行っているように、または他のいくつかの方法でラッパーを使用することもできます。私はラッパーで+1です。(バイトコードハックが必要な場合はお知らせくださいが、それらは楽しいと思います。StackOverflowで回答として提供することのすばらしい点は、それらを作成できることですが、使用する必要はありません;)

Q3、Q4。あまり。イテレータの10番目の要素を取得するには、以前の要素をすべて実行する必要があります。最初の要素が必要であることがわかっている場合は、

smallest = next(sorted_iterator)

そして最後に

for item in iterable: pass
largest = item

最初の要素はイテレーターの最初の要素を食べ、最後の要素はイテレーター全体を食べます。バイバイイテレータ。

于 2010-11-28T07:42:43.030 に答える