Реверс списка без использования встроенных функций
Я использую Python 3.5.
в рамках проблемы я пытаюсь создать функцию, которая принимает список в качестве входных данных и возвращает его. Так что если x = [a, b, c]
функция сделает x = [c, b, a]
.
проблема в том, что мне не разрешено использовать какие-либо встроенные функции, и это заставило меня застрять. Моей первоначальной мыслью был следующий цикл внутри функции:
for revert in range(1, len(x) + 1):
y.append(x[-revert])
и это работает. Но проблема в том, что я использую len(x)
, который я считаю встроенной функцией, правильно?
поэтому я искал вокруг и сделал следующий очень простой код:
y = x[::-1]
который делает именно то, что я хотел, но это просто кажется почти слишком простым/легким, и я не уверен, что "::"
считается функция.
поэтому мне было интересно, есть ли у кого-нибудь подсказки/идеи, как вручную спроектировать указанную функцию? Это просто кажется очень сложным, когда вы не можете использовать встроенные функции, и я застрял на некоторое время.
8 ответов
range
и len
как встроенные функции. С list
методы принимаются, вы можете сделать это с insert
. Это reeaallyy медленно* но он делает работу для маленький списки без использования каких-либо встроенных модулей:
def rev(l):
r = []
for i in l:
r.insert(0, i)
return r
непрерывно вставляя в нулевое положение, вы получаете обратную версию входного сигнала список:
>>> print(rev([1, 2, 3, 4]))
[4, 3, 2, 1]
делаем:
def rev(l):
return l[::-1]
также можно считать решением. ::-1
(::
имеет другой результат) не является функцией (это срез) и []
это, опять же, метод списка. Кроме того, контрастные insert
, это быстрее и читабельнее; просто убедитесь, что вы в состоянии понять и объяснить это. Хорошее объяснение того, как это работает, можно найти В С. О. ответ.
*Reeaaalllyyyy медленно, ознакомиться с juanpa.ответ arrivillaga для прохладного сюжета и append
С pop
и взгляните на in-place reverse
по спискам, как это сделано в ответ Йоав Glazner по.
::
- это не функция, это питон литерал. а также []
Как проверить, если ::, []
функции или нет. Просто,
import dis
a = [1,2]
dis.dis(compile('a[::-1]', '', 'eval'))
1 0 LOAD_NAME 0 (a)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 2 (-1)
12 BUILD_SLICE 3
15 BINARY_SUBSCR
16 RETURN_VALUE
если ::,[]
были функции, вы должны найти метку CALL_FUNCTION
среди инструкций python, выполняемых a[::-1]
заявление. Значит, это не так.
посмотрите, как выглядят инструкции python, когда вы вызываете функцию, скажем list()
функции
>>> dis.dis(compile('list()', '', 'eval'))
1 0 LOAD_NAME 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
так, в основном
def rev(f):
return f[::-1]
работает нормально. Но, я думаю, вы должны сделать что-то, как Джим предложил в своем ответе, если ваш вопрос домашнее задание или послал вас учитель. Но вы можете добавить этот самый быстрый способ в качестве примечания.
если вы учитель жалуется [::-1]
нотация, покажите ему пример, который я вам дал.
другой способ ( просто для полноты картины :) )
def another_reverse(lst):
new_lst = lst.copy() # make a copy if you don't want to ruin lst...
new_lst.reverse() # notice! this will reverse it in place
return new_lst
вот решение, которое не использует встроенный функции но полагается на методы списка. Он обратный на месте, как подразумевается вашей спецификацией:
>>> x = [1,2,3,4]
>>> def reverse(seq):
... temp = []
... while seq:
... temp.append(seq.pop())
... seq[:] = temp
...
>>> reverse(x)
>>> x
[4, 3, 2, 1]
>>>
ПВП
Джим, ваш ответ с помощью insert
в позиции 0 сводил меня с ума! Это решение квадратичное время! Вы можете использовать append
и pop
С временным списком для достижения линейного времени с помощью простых методов списка. Смотри (reverse
в синий, rev
is зеленый):
если это немного похоже на "обман" с помощью seq[:] = temp
, мы всегда можем перебрать temp
и добавить каждый элемент в seq
и сложность времени по-прежнему будет линейной, но, вероятно, медленнее, поскольку она не использует внутренние элементы на основе C.
ваш пример, который работает:
y = x[::-1]
использует Python нотация срезов что не является функцией в том смысле, в каком я предполагаю, что вы запрашиваете. По существу ::
действует как разделитель. Более подробная версия вашего кода будет:
y = x[len(x):None:-1]
или
y = x[start:end:step]
Я, вероятно, не жаловался бы, что python делает вашу жизнь очень, очень легко.
редактировать, чтобы быть супер педантичным. Кто-то может возразить, что зову []
вообще использует встроенную функцию python, потому что это действительно синтаксический сахар для метода __getitem__()
.
x.__getitem__(0) == x[0]
и с помощью ::
делает использование
другой способ для полноты, range()
принимает необязательный параметр шага, который позволит вам сделать шаг назад по списку:
def reverse_list(l):
return [l[i] for i in range(len(l)-1, -1, -1)]
самый питонический и эффективный способ достичь этого-срезать список. И, поскольку вы упомянули, что вам не нужна встроенная функция, этого вполне достаточно для вашего требования. Например:
>>> def reverse_list(list_obj):
... return list_obj[::-1]
...
>>> reverse_list([1, 3, 5 , 3, 7])
[7, 3, 5, 3, 1]
просто повторите список справа налево, чтобы получить элементы..
a = [1,2,3,4]
def reverse_the_list(a):
reversed_list = []
for i in range(0, len(a)):
reversed_list.append(a[len(a) - i - 1])
return reversed_list
new_list = reverse_the_list(a)
print new_list