2017-07-08 4 views
2

イテレータを使用して生成された数値のシーケンスに特定の値が属するかどうかをテストしたいと思います。もちろん、の値がの場合、その値が満たされるとすぐに停止することができます。しかし、が入っていないときは、それが問題だと思います。イテレータによって値が生成されないかどうかをテストする

しかし、追加情報を使用することができます(たとえば、シーケンスが増加しているなど)。

フィボナッチ例考えてみましょう:8はシーケンスに属しているかどうかを1つのテストはその後、すべてがうまくている場合

class FibonacciIterator(object): 
    def __init__(self): 
     self.mem = [0, 1] 
    def __next__(self): 
     curr = self.mem[0] 
     new = self.mem[0]+self.mem[1] 
     self.mem[0] = self.mem[1] 
     self.mem[1] = new 
     return curr 

class Fibonacci(object): 
    def __iter__(self): 
     return FibonacciIterator() 

を:

>>> fib = Fibonacci() 
>>> 8 in fib 
True 

しかし、1が属していない10を(テストし、場合シーケンスに)

決してt erminates。しかし、813となった後、そして配列が必然的に増加しているので、not 10 in fibがあることを観察することによって、10が配列中にないことを容易に判定することができる。

inのような振る舞いを実装するための良い方法がPythonにあるので、10 in fibは終了しますか?

+2

あなたは順序が単調に増加していることを知っている '__contains__'の定義を提供することができます。しかし、ジェネレータの場合、 '__contains__'はシーケンスを消費する*ので、特に有用ではありません。 – chepner

+0

は、天気をテストしていない場所で問題が発生している可能性があります。数値が入力を超過しました。 – VIPER

+0

@chepner実際には、イテレータが消費されるという事実は、上記の例では大したことではありません。 '__contains__' 'in'が使用されるたびに新しい' FibonacciIterator'( "iterator")を生成する 'Fibonacci'クラス(" iterable ") –

答えて

1

自明な解は、反復子のコピーを超えるだけ繰り返し処理__contains__メソッドを実装するために、次のようになります。

class FibonacciIterator(object): 
    def __init__(self): 
     self.mem = [0, 1] 

    def __iter__(self): 
     return self 

    def __contains__(self, value): 
     testit = FibonacciIterator() 
     testit.mem = list(self.mem) # copy 
     for item in testit: 
      if item == value: 
       return True 
      if item > value: 
       return False 

    def __next__(self): 
     curr = self.mem[0] 
     self.mem = self.mem[1], sum(self.mem) 
     return curr 

class Fibonacci(object): 
    def __iter__(self): 
     return FibonacciIterator() 

    def __contains__(self, value): 
     return value in iter(self) 

数はフィボナッチ数であるかどうかを判断する別の方法があるしかし:どちらか(5*n**2 + 4)場合や、 (5*n**2 – 4)またはその両方が完全な正方形(整数の2乗)です。

私はis_square機能を実装するためにthis answerからのアプローチを使用します:

def is_square(apositiveint): 
    # Source: https://stackoverflow.com/a/2489519/5393381 
    # Credit: Alex Martelli 

    x = apositiveint // 2 
    seen = {x} 
    while x * x != apositiveint: 
     x = (x + (apositiveint // x)) // 2 
     if x in seen: 
      return False 
     seen.add(x) 
    return True 

class FibonacciIterator(object): 
    def __init__(self): 
     self.mem = [0, 1] 

    def __iter__(self): 
     return self 

    def __contains__(self, value): 
     if value < self.mem[0]: 
      return False 
     else: 
      # Just check if at least one of both is a perfect square 
      value_squared_times_five = 5*value**2 
      return is_square(value_squared_times_five + 4) or is_square(value_squared_times_five - 4) 

    def __next__(self): 
     curr = self.mem[0] 
     self.mem = self.mem[1], sum(self.mem) 
     return curr 

class Fibonacci(object): 
    def __iter__(self): 
     return FibonacciIterator() 

    def __contains__(self, value): 
     return value in iter(self) 
関連する問題