2014-04-20 24 views
1
def is_correct_sequence(seq): 
    """ 
    Check whether the given sequence does not contain 
    the same value (except for None) more than once, 
    and whether it only contains (1) integer values between 1 
    and the length of the given sequence and/or (2) the special value None. 
    """ 

    for i in range(len(seq)): 
     if seq[i] < 1 or seq[i] > len(seq): 
      return False 
     elif type(seq[i]) != type(None) or type(seq[i]) != int: 
      return False 
     else: 
      for i in range(len(seq)-1): 
       for j in range(i+1, len(seq)): 
        if seq[i] == seq[j] != None: 
        return False 
        else: 
        return True 

##TESTS 

assert not is_correct_sequence((4, "abc", None, -17, None, "xyz")) 
assert not is_correct_sequence((1, 2, 1)) 
assert not is_correct_sequence((1.0, None, 1)) 
assert is_correct_sequence((None, None, 4, 1)) 
assert is_correct_sequence((None, 1, 2, 3)) 

我有最後2個斷言的問題。所以目標不是刪除雙打,而是要看看序列是否正確。如果其中兩個元素相同,則順序不正確(除無)(無可能多次出現)。我如何在我的代碼中清楚地說明這一點?Python:is_correct_sequence(沒有雙打)

+1

在每種情況下,您都有一個'return'子句。你永遠不會做一次以上的迭代。 –

回答

0

您的代碼存在一些問題。

一個主要的問題是,你永遠不會真正檢查每個元素不止一次 - 當你的代碼命中「返回」語句時,它立即返回,並不檢查每一個其他語句。當你需要返回False時,這是有效的,因爲如果有什麼東西False,你不需要檢查序列的其餘部分。

然而,在該行的一個問題,當你返回True,因爲你還沒有排除的是,子可能是不正確的以後。

另一個問題是,你的if語句中的條件微妙地偏離 - 嘗試仔細觀察並找出他們實際正在做的事情。採取這些考慮進去,你的代碼的正確版本是:

def is_correct_sequence(seq): 
    for i in range(len(seq)): 
     if seq[i] is not None and (seq[i] <= 1 and seq[i] >= len(seq)): 
      # This check previously failed if seq[i] was None, and did not 
      # check the bounds properly 
      return False 
     elif seq[i] is not None and type(seq[i]) != int: 
      # Use 'and', not 'or' 
      return False 
     else: 
      for i in range(len(seq)-1): 
       for j in range(i+1, len(seq)): 
        if seq[i] == seq[j] and seq[i] is not None and seq[j] is not None: 
         # Again, same thing. This failed if either seq[i] or seq[j] 
         # were not equal to None 
         return False 
    return True 

正如代碼所指出的,你的主要問題是不檢查,看看如果一個項目是等於無。如果是這樣,在與數字進行比較時會得到奇怪的結果。

順便提一下,在Python中檢查元素是否爲None或不是None的正確方法是成語item is Noneitem is not None

然而,編寫代碼更簡潔的方式可能是這樣的:

def is_correct_sequence(seq): 
    nums = [a for a in seq if a is not None] 
    allowed_types = (type(None), int) 

    contains_correct_types = all(isinstance(a, allowed_types) for a in seq) 
    numbers_within_bounds = all(1 <= a <= len(seq) for a in nums) 
    numbers_are_unique = len(nums) == len(set(nums)) 
    # Set returns a version of a list with all duplicates removed 

    return contains_correct_types and numbers_within_bounds and numbers_are_unique 

而不是使用一個for循環,我們可以使用列表內涵和發電機內涵以及內建anyall功能的更清楚地表達你的代碼的意圖。

0

嘗試通過以下方法,看看它是否有意義。我只用你提供的斷言來測試它,它似乎工作。

def is_correct_sequence(seq): 
    return has_unique_values(seq) and has_correct_range(seq) 

def has_unique_values(seq): 
    """ 
    Check whether sequence contains the same value (excluding None) more than once 

    Returns True if all values are unique or None, False otherwise. 
    """ 

    nones = seq.count(None) 
    seq_set = set(seq) 

    if nones: 
     if len(seq) != (len(seq_set) + nones - 1): 
      return False 
    else: 
     if len(seq) != len(seq_set): 
      return False 

    return True 

def has_correct_range(seq): 
    """ 
    Check whether sequence contains integer values between 1 and the length 
    of the given sequence and/or the special value None. 
    """ 

    accepted_range = range(1, len(seq) + 1) 
    for e in seq: 
     if e not in accepted_range and e is not None: 
      return False 

    return True 

assert not is_correct_sequence((4, "abc", None, -17, None, "xyz")) 
assert not is_correct_sequence((1, 2, 1)) 
assert not is_correct_sequence((1.0, None, 1)) 
assert is_correct_sequence((None, None, 4, 1)) 
assert is_correct_sequence((None, 1, 2, 3)) 
0

下面是通過一個緊湊型的所有斷言:

from collections import Counter 

def is_correct_sequence(seq): 

    len_seq = len(seq) 
    counts = Counter(seq) 

    for value, count in counts.items(): 

     # Never check None items 
     if (value is not None and (

      # Does the value occur more than once 
      # or has it a bad type (no integer)? 
      (count > 1 or not isinstance(value, int)) or 

      # Or is the integer not in the valid range? 
      (value < 1 or value > len_seq)) 
      ): 

      # Sequence is in correct! 
      return False 

    return True 


assert not is_correct_sequence((4, "abc", None, -17, None, "xyz")) 
assert not is_correct_sequence((1, 2, 1)) 
assert not is_correct_sequence((1.0, None, 1)) 
assert is_correct_sequence((None, None, 4, 1)) 
assert is_correct_sequence((None, 1, 2, 3)) 

您應該使用

  • isinstance()類型檢查
  • is None/is not None而不是== None/!= None
  • 這種簡單測試沒有嵌套循環(collections.Counter應該使我的解決方案非常高效)