2015-10-29 4 views
0

Я начинаю программировать на Python, и у меня проблемы с некоторыми материалами.Looping с последовательными элементами

Итак, я хочу написать функцию, которая возвращает логическое значение. Функция информирует пользователя о том, есть ли повторяющаяся пара элементов в списке, который он ввел. Кстати, я хочу это сделать, используя только len(), range(), loops, if-statements, переменные и арифметические функции (без встроенных функций).

Например:

contains_consecutive_duplicates([1,3,3]) should return True 

contains_consecutive_duplicates([3,2,3]) should return False 

Мой код:

def contains_consecutive_duplicates(xs): 
    for i in xs: 
     if xs[i] == xs[i-1] or xs[i] == xs[i+1]: 
      return True 
     else: 
      return False 

Моя логика это следующим образом: Каждый раз, когда цикл будет работать, i бы сослаться на какой-то элемент в списке. Если этот элемент был таким, что перед ним или после него он был равен ему, тогда цикл for вернет true. Если нет, продолжайте поиск. Если их нет, он вернет false.

Теперь я действительно понимаю, где ошибка (я думаю). Проблема в том, что я не знаю, как ее решить. Я думаю, что цикл for начинает сталкиваться с проблемой в начале (когда i ссылается на 0-й элемент). Там нет элемента до 0-го элемента, следовательно, ошибка:

"index out of range" 

P.S: Это как вы возвращаете логическое значение?

Есть ли лучший способ сделать это?

Я был бы признателен за предоставленную помощь! Заранее спасибо!

+2

'для г в xs' перебирает значения в массиве, а не по индексам. – roeland

+0

Кроме того, проблема, с которой вы можете столкнуться, заключается в проверке следующего элемента в списке. Если у вас есть список, который подходит только для xs [4], функция попытается проверить значение xs [5], но поскольку нет xs [5], здесь вы получите ошибку индекса – dbishop

ответ

-1

Это должно сделать трюк:

def contains_consecutive_duplicates(xs): 
    for i in range(1, len(xs) - 1): 
     if xs[i] == xs[i-1] or xs[i] == xs[i+1]: 
      return True 
    return False 

Он итерирует через все значения бара, в первый и последний (созданный с помощью функции диапазона), возвращение (который заканчивается цикл), если он находит дубликат. Если он достигает конца и не нашел дубликата, он не должен существовать, поэтому он возвращает False.

+0

Нет никаких оснований проверять как вперед, так и назад. Пока вы проверяете правильные индексы, тестирование только в одном направлении поймает все дубликаты с половиной сравнения. – ShadowRanger

+0

@ShadowRanger Да, вы совершенно правы. Я действительно думаю, что другие ответы лучше, но поскольку это учебное упражнение для ученика, я предпочитаю делать как можно меньше изменений в коде, поэтому они не путаются, изучая все сразу. – Knells

+0

Спасибо, что действительно помогло !!!! – AbSaintDane

1

Попробуйте это:

def contains_consecutive_duplicates(xs): 
    for i in xs: 
     if xs.indexOf(i)==len(xs): 
      break 
     if xs[i] == xs[i-1] or xs[i] == xs[i+1]: 
      return True 
     else: 
      return False 

Что вы делаете, пытается сделать это оценить xs[i+1], но не существует.

+0

Это не означает, t исправить проблему, пытаясь использовать в ней значения «xs» как «индексы» (которые только на самом деле проверяли бы последовательные индексы, если бы значения были целыми целыми числами). И тест для 'len' не будет препятствовать запуску' + 1' теста 'IndexError', потому что' len (xs) 'не является допустимым индексом, поэтому' i' передаст тест, но 'i + 1' будет ошибка. – ShadowRanger

+0

.. и, кроме тех, вы только посмотрите на 'i = xs [0]', потому что 'if' немедленно возвращает либо True, либо False. – DSM

+0

Кричит, я исправил его – AMACB

2

@roeland указал на проблему, предполагая, что итерация list приведет вас к индексам (если вы хотите индекс и значение, используйте enumerate). Но в этом случае вам действительно не нужен индекс.

Для простого случая (где это известно, контейнер можно порезать), вы можете просто перебирать с zip ломтиками над офсетных:

def contains_consecutive_duplicates(xs): 
    return any(x == y for x, y in zip(xs, xs[1:])) 

Более общие решения могут быть сделаны с itertools.groupby обрабатывать случай где вы не можете срезать, но это просто и не требует импорта.

Использование any в этом случае является лишь короткой рукой, чтобы разделить выражение генератора и вернуть True, если любые значения являются правдивыми.Долгая эквивалентная форма:

def contains_consecutive_duplicates(xs): 
    for x1, x2 in zip(xs, xs[1:]): 
     if x1 == x2: 
      return True 
    return False 

Так как ваш учитель, видимо, думает, что Модульные плохо, но len и range не встроенные модули (они), вы можете сделать это немой путем:

def contains_consecutive_duplicates(xs): 
    for i in range(len(xs) - 1): 
     if xs[i] == xs[i+1]: 
      return True 
    return False 

Что делает то же самое, что и zip ing, менее эффективно (генерирование целых чисел индекса и явное индексирование на Python на удивление дорогостоящее относительно собственной итерации).

+0

Примечание: для большей скорости/краткости, но немного менее очевидного поведения, 'return' может быть' return any (map (eq, xs, xs [1:])) ', если вы включаете' from оператор import eq' (и на Py2 'from future_builtins import map'), но это попадает в сорняки, и это менее интуитивно для новых программистов. – ShadowRanger

1

Используя только range, for и if заявления, это может быть сделано с:

def contains_consequtive_duplicates(xs): 
    for i in range(len(xs)-1): 
     if xs[i] == xs[i+1]: return True 
    return False 

списки доступа к вам с их index и не по их стоимости (который вы с помощью for i in list). Кроме того, если вы выполните проверку xs[i] == xs[i-1], это не даст результата, которого вы хотите, так как x[-1] проверит конец списка, так что [3, 2, 3] вернет True.

В небольшой демонстрации:

if contains_consequtive_duplicates([1,3,3]): print "consecutive" 
# Prints Consequtive 

if contains_consequtive_duplicates([3, 2, 3]): print "consecutive" 
# Prints nothing 
+0

Я считаю, что вы хотите сохранить явное выражение «return False» там; возврат по умолчанию «Нет» является ложным, но назначение, похоже, чрезмерно связано с возвратом, являющимся фактическим «bool». – ShadowRanger

1

Это должно сделать:

>>> def contains_consecutive_duplicates(xs): 
... for i, v in enumerate(xs[:-1]): 
...  if v == xs[i+1]: 
...  return True 
...  else: 
...  pass 
... return False 
>>> l1 = [1,3,3] 
>>> l2 = [1,3,2] 
>>> l3 = [] 
>>> l4 = [2] 
>>> contains_consecutive_duplicates(l1) 
True 
>>> contains_consecutive_duplicates(l2) 
False 
>>> contains_consecutive_duplicates(l3) 
False 
>>> contains_consecutive_duplicates(l4) 
False 
>>> 
Смежные вопросы