检查具有特定条件的连续数字 - Python

时间:2017-05-17 10:32:32

标签: python

我试图编写一个函数来测试列表是否具有连续数字但是具有非常奇怪的捕获。问题在于" a"可以用作任何整数的替代,但列表中至少有2个元素必须是数字。元素> = 1(如果不是" a")并且是整数。可以假设输入是这种形式,因此不需要检查它。 我对编码很陌生,所以我实际上更喜欢在一个衬垫上使用循环,因为我还不熟悉一个衬垫的使用。

例如:

>>>check_consecutive([1,2,"a","a",5,6,7,"a"])
True
>>>check_consecutive(["a","a","a","a",9,10])
True
>>>check_consecutive(["a","a","a","a",5])
False #Need at least 2 elements to be numbers
>>>check_consecutive([3,4,5,"a",6,7])
False
>>>check_consecutive(["a","a","a","a","a","a",2,3])
False

我试图做的事情:

def check_consecutive(lst):
 count = 0
 for i in range(len(lst)-1):
     if lst[i] == "a" or lst[i+1] == "a":
         count +=1
     elif lst[i+1] - lst[i] == 1:
         count +=1
 if count == len(lst)-1:
     return True
 return False

这不起作用,因为它没有考虑" a"的值。我不确定该怎么做。提前感谢您的帮助。

6 个答案:

答案 0 :(得分:3)

尝试以下方法。它适用于所有测试用例,并且我将单行保持在最低限度:

def check_consecutive(lst):
    # Check for the number of non-"a" entries in the list:
    if len([x for x in lst if x != "a"]) < 2:
        return False

    # Get the first non-a value (ASSUMPTION: this is a number)
    first_number = next((e for e in lst if e != "a"), None)

    # Find the index of the first number
    first_index = lst.index(first_number)

    # Find the difference between the first number and its index
    diff = first_number - first_index

    # Based on the final example - false if negative values would be used:
    if diff < 0:
        return False

    # Create a new list - replace a's with their index plus the difference we found
    # If the list is consecutive, this difference will be consistent for all values
    all_numbers = []
    for i, x in enumerate(lst):
        if x == "a":
            all_numbers.append(i + diff)
        else:
            all_numbers.append(x)

    # Check if the values are now consecutive or not!
    if all(all_numbers[i+1] == all_numbers[i] + 1 for i in range(len(all_numbers) - 1)):
        return True
    else:
        return False

print check_consecutive([1,2,"a","a",5,6,7,"a"])
#True
print check_consecutive(["a","a","a","a",9,10])
#True
print check_consecutive(["a","a","a","a",5])
#False #Need at least 2 elements to be numbers
print check_consecutive([3,4,5,"a",6,7])
#False
print check_consecutive(["a","a","a","a","a","a",2,3])
#False

如果您想了解一些单行工作的方式,可以按如下方式略微降低功能:

def check_consecutive(lst):
    # Check for the number of non-"a" entries in the list:
    if len([x for x in lst if x != "a"]) < 2:
        return False

    # Get the first non-a value (ASSUMPTION: this is a number)
    first_number = next((e for e in lst if e != "a"), None)

    # Find the index of the first number
    first_index = lst.index(first_number)

    # Find the difference between the first number and its index
    diff = first_number - first_index

    # Based on the final example - false if negative values would be used:
    if diff < 0:
        return False

    if all(x == "a" or x == i + diff for i, x in enumerate(lst)):
        return True
    else:
        return False

答案 1 :(得分:1)

这里有一个有效的解决方案。我知道你说你不想要列表推导(我用for循环编辑它所以你可以理解):

def check_consecutive(a):
    b = [(next(y for y in a if y!='a')-a.count('a') if a[0] == 'a' else a[0])+i if x=='a' else x for i, x in enumerate(a)]
    return len(a) - a.count('a') >= 2 and b[0] >= 0 and range(b[0],b[-1]+1) == b

列表理解可以转化为:

for i,x in enumerate(a):
     if x == 'a':
         if a[0] == 'a':
             #              |---> Gets first integer from list
             new_lst.append(next(x for x in a if x != 'a') - a.count('a'))
         else:
             new_lst.append(a[0]+i)
     else:
         new_lst.append(x)

答案 2 :(得分:1)

这不是那么好的解决方案。但我像这样向后试过这个名单 -

def check_consecutive(lst):
  last = 0
  number_count = len(lst) - lst.count('a')
  # Check count of numbers and return if less than 2
  if number_count < 2:
      return False

  for i in reversed(range(len(lst))):
      # last 0 means no numbers encountered yet
      if not last:
          last = lst[i] if lst[i] != "a" else 0
          continue
      else:
          # If current element is number check consecutive property
          if lst[i] != "a" and last - lst[i] != 1:
              return False

          # Recalculate last
          last -= 1

          # If last falls below permissible range, return 
          if last < 1:
              return False

  # If all condition satisfied, it is a hit. Whew!!!
  return True

print check_consecutive([1,2,"a","a",5,6,7,"a"])
print check_consecutive(["a","a","a","a",9,10])
print check_consecutive(["a","a","a","a",5])
print check_consecutive([3,4,5,"a",6,7])
print check_consecutive(["a","a","a","a","a","a",2,3])

答案 3 :(得分:1)

它适用于您的示例(py 2.7):

def check_consecutive(lst):
    # what could be the list
    cond = [0,1]
    n_sum = False
    for x in lst:
        if not(cond[1]) and x!= 'a':
            n_sum = True;
            if (cond[0] - x) != (lst.index(cond[0]) - lst.index(x)): 
                return False
            elif x <= lst.index(x):
                return False
        if x!='a' and cond[1]:
            cond[0] = x;
            cond[1] = 0;
    print cond
    return n_sum

答案 4 :(得分:1)

所有测试用例都假设序列以实际数字(或两者)开头或结尾。假设这是真的,我们可以在O(n)时间和O(1)空间中提出非常简单的显式解决方案。

def check_consecutive(seq):
    PLACEHOLDER = 'a'
    # O(n) check for preconditions
    if sum(obj != PLACEHOLDER for obj in seq) < 2:
        return False
    if isinstance(seq[0], int):
        # first element known, incrementing
        incrementing = True
        delta = 1
    else:
        # last element known, decrementing
        incrementing = False
        delta = -1
    # iterate from first or last element
    iterator = iter(seq) if incrementing else reversed(seq)
    # consume first value
    previous_item = next(iterator)
    # check if our assumption is correct
    assert previous_item != PLACEHOLDER
    # O(n) check for valid sequence
    for item in iterator:
        # figure out expected placeholder value
        if item == PLACEHOLDER:
            item = previous_item + delta
        # check if next value matches requirements of valid solution
        if item <= 0 or item != (previous_item + delta):
            return False
        previous_item = item
    return True

assert check_consecutive([1,2,"a","a",5,6,7,"a"]) is True
assert check_consecutive(["a","a","a","a",9,10]) is True
assert check_consecutive(["a","a","a","a",5]) is False
assert check_consecutive([3,4,5,"a",6,7]) is False
assert check_consecutive(["a","a","a","a","a","a",2,3]) is False

答案 5 :(得分:1)

所有其他答案可能都有效,但我尽量保持简单,直截了当,希望它有所帮助:)代码应该是不言自明的。

def check_consecutive(input_list):
    # First find the first element that is not equal to a to figure out the start of the sequence
    start_seq = None
    for i, el in enumerate(input_list):
        if el != 'a':
            # Now we know the number the sequence should start with.
            # For example the first 2 elements are a, and the first "non-a" element is 5
            # Then the loop breaks when el = 5, and i = 2, meaning the start should be 3
            start_seq = el - i
            break

    # If the whole list exists of a's, then start will still be None and the function should return false
    if start_seq is None:
        return False

    if start_seq < 1:
        return False

    # Now we can loop over the list, keep replacing a's by what they should be
    # Create some values for bookkeeping
    num_n = 0
    old_value = start_seq - 1
    for el in input_list:
        if el != 'a':
            num_n += 1
            if el != (old_value + 1):
                return False

        # increment old value
        old_value += 1

    if num_n < 2:
        return False

    return True