2013-12-12 2 views
0

просто делают вывод из моего класса python и замечают, что я забыл, как это сделать. Я знаю, что это супер просто, и я что-то пропускаю, но я был бы рад помочь!pop() Средние два элемента из списка

def outsideIn2(lst): 

'''(list)->list 

Returns a new list where the middle two elements have been 
removed and placed at the beginning of the result. Assume all lists are an even 
length 

>>> outsideIn2(['C','a','r','t','o','n']) 
['r','t','C','a','o','n'] # rt moves to front 
>>> outsideIn2(['H','i']) 
['H','i'] # Hi moves to front so output remains the same. 
>>> outsideIn2(['B','a','r','b','a','r','a',' ','A','n','n','e']) 
['r','a','B','a','r','b,','a',' ','A','n','n','e'] # ra moves to front. 
''' 
length = len(lst) 
middle1 = lst.pop((len(lst)/2) - 1) 
middle2 = lst.pop((len(lst)/2) + 1) 

lst.insert([0], middle1) 
lst.insert([1], middle2)     

return lst 

Я получаю эту ошибку:

middle1 = lst.pop((len(lst)/2) - 1)

TypeError: integer argument expected, got float

Что я делаю неправильно?

+0

Является ли это python 3.x? – dansalmo

+1

В качестве побочного примечания, после того, как вы поп 'len (lst)/2-1', все остальное сдвигает один слот. Это делает вашу математику намного легче, если вы сначала поместите верхнюю. Или, в качестве альтернативы, если вы поместите и снова вставьте его перед появлением и повторным вставкой другого (потому что popping 'len (lst)/2-1' и вставка' 0' оставляет другой в исходном месте). – abarnert

ответ

4

Когда вы обновили до Python 3, оператор '/' изменил свое действие на то, чтобы дать вам целочисленное деление на реальное деление. Переключитесь на «//».

+1

Один очень незначительный вопрос: Python явно называет его тип 'float', а не' real', чтобы забивать дом тем фактом, что это не _really_ действительное число, но с плавающей точкой base-2 рационально, и оно вызывает '/' "true разделение ", а не" реальное "или" плавающее "подразделение. – abarnert

1

Вы можете использовать // оператор:

middle1 = lst.pop((len(lst) // 2) - 1) 
1

Другие ответы объясняется, почему вы получаете ошибку. Вам нужно использовать // вместо / (также, только для записи, вам нужно указать list.insert целых чисел, а не списки).


Однако, я хотел бы предложить другой подход, который использует Explain Python's slice notation:

def outsideIn2(lst): 
    x = len(lst)//2 
    return lst[x-1:x+1]+lst[:x-1]+lst[x+1:] 

Этот метод должен быть значительно быстрее, чем при использовании list.pop и list.insert.

В качестве доказательства, я сделал ниже сценарий, чтобы сравнить два метода с timeit.timeit:

from timeit import timeit 

def outsideIn2(lst): 

    length = len(lst) 
    middle1 = lst.pop((len(lst) // 2) - 1) 
    middle2 = lst.pop((len(lst) // 2) + 1) 

    lst.insert(0, middle1) 
    lst.insert(1, middle2) 

    return lst 

print(timeit("outsideIn2(['B','a','r','b','a','r','a',' ','A','n','n','e'])", "from __main__ import outsideIn2")) 

def outsideIn2(lst): 
    x = len(lst)//2 
    return lst[x-1:x+1]+lst[:x-1]+lst[x+1:] 

print(timeit("outsideIn2(['B','a','r','b','a','r','a',' ','A','n','n','e'])", "from __main__ import outsideIn2")) 

Результаты были следующими:

6.255111473664949 
4.465956427423038 

Как вы можете видеть, предлагаемый мною метод был ~ На 2 секунды быстрее. Тем не менее, вы можете запустить больше тестов, если хотите проверить мои данные.

+0

Ты взял слова прямо из моего мозга! Я думал, что это будет быстрее, но время это доказывает, хорошо! – PaulMcG

+1

@PaulMcGuire - Спасибо. К сожалению, для вас, однако, мой метод быстрее, чем ваш, почему-то.^_^Вы можете убедиться сами, скопировав тестовый сценарий, который я сделал, и заменив его функцией. Держу пари, вы могли бы исправить это, поставив последние две строки в одну, чтобы вы не делали кортеж. – iCodez

+0

@PaulMcGuire - Да, это сработало. Ввод этих двух линий в один делает наши решения шеи и шеи для скорости. – iCodez

0

Использование pop и insert (особенно вставка в позициях 0 и 1) может быть довольно медленным с помощью списков Python. Поскольку базовое хранилище для списка представляет собой массив, вставка в положение 0 означает, что элемент в позиции n-1 должен быть перемещен в положение n, тогда элемент в n-2 должен быть перемещен в n-1 и так далее. pop должен сделать то же самое в обратном порядке. Итак, представьте в своем маленьком методе, сколько должно выполняться элементов элемента. Грубо говоря:

pop #1 - move n/2 elements 
pop #2 - move n/2 elements 
insert 0 - move n elements 
insert 1 - move n elements 

Так примерно 3n ходы делаются в этом коде.

Разорвать список на 3 дольки и сборку нового списка может быть более оптимальным:

def outsideIn2(lst): 
    midstart = len(lst)//2-1 
    left,mid,right = lst[0:midstart], lst[midstart:midstart+2], lst[midstart+2:] 
    return mid+left+right 

Кроме того, вы не столкнетесь с любыми странными вопросами по pop изменения длины списка между первым и вторым позвоните по номеру pop. И фрагменты неявно защищают от ошибок индекса, когда вы получаете список, который короче 2 символов.