Модераторы: Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Python] Удаление дубликатов. 
V
    Опции темы
Paranorma
Дата 16.1.2007, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 102
Регистрация: 1.1.2007

Репутация: 1
Всего: 1



Необходимо удалить из списка дубликаты. Насколько я понимаю алгоритм такой, что тут элементы должны сравниваться друг с другом и один из двух одинаковых удаляться, то есть это как мне кажется такую программку можно написать с использованием цикла while 
a = [45, 1, 34, 12, 78, 45, 12, 1, 34] вот мой список (он изначально заполнен целыми числами)
Что дальше?
PM MAIL Skype Jabber MSN   Вверх
kot_matros
Дата 17.1.2007, 01:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 11.1.2007

Репутация: нет
Всего: нет



Код

a=[45, 1, 34, 12, 78, 45, 12, 1, 34]

for i in range( len( a ) ):
    print a[i],
print

for i in range( len( a ) ):
    c=a[i]
    for j in range( len( a ) ):
        if a[j]==c and i<j:  a[j]=[] 
        else: pass

for i in range( len( a ) ):
    print a[i],

PM MAIL   Вверх
Paranorma
Дата 17.1.2007, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 102
Регистрация: 1.1.2007

Репутация: 1
Всего: 1



Люди!!! Спасайте!!!
Препод убивец опять недоволен. У меня с циклом while проблемы и я вынуждена сейчас все задачи решать с его использованием. Вчера я написала так:


Код
a = [45, 1, 34, 12, 78, 45, 12, 1, 34]
i = 0
while i < len(a):
    s = a[i]
    if s 

Дальше застопорилась...

Получила от препода электронное письмо:


Я совсем забыл сказать что set пользовать нельзя,
в этом случае задача становиться тривиальной.

Теперь обратимся ко второму фрагменту. 
Если посмотреть на второй фрагмент, то строчку
 if s
надо убрать и вместо ее надо вставить фрагмент 
который сравнивает a[i] (или s) с элементами списка 
идущими после него и если какой то из последующих элементов
равен a[i] то его надо удалить.
Для организации такого сравнения надо
использовать второй цикл вложенный в первый. 
В качестве переменной второго цикла можно взять j.
Особое внимание надо уделить тому в каких пределах 
меняется перменная j.


То есть один while вложен в другой.


Код
a = [45, 1, 34, 12, 78, 45, 12, 1, 34]
i = 0
while i < len(a):
    s = a[i]
    j = 0
    while j < len(a):
        c = s[j]
        if s = c:
             del

Вот такой фрагмент я написала. Не знаю насколько он верный и как организовать сравнение элементов. Что написать после del? И верно ли это while j < len(a): (написала так, ориентируясь на слова препода "Особое внимание надо уделить тому в каких пределах 
меняется перменная j.") То есть ведь идет сравнение элементов в СПИСКЕ.
Дальше-то что???

PM MAIL Skype Jabber MSN   Вверх
doomik
Дата 17.1.2007, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Одинокий волк
**


Профиль
Группа: Участник
Сообщений: 360
Регистрация: 25.10.2005
Где: #vingrad

Репутация: 3
Всего: 15



Код

a = [45, 1, 34, 12, 78, 45, 12, 1, 34]
# 45 1 34 12 78
i = 1
j = 0
while j < (len(a))-1:
    while i < (len(a)):
        if a[j] == a[i] and j != i: # Делаем проверку если а елемент равен а + 1 и если i != j 
            del a[i] # Удаляем повторяющийся елемент
        i += 1  # Продвигаем счётчик на 1 шаг 
    j += 1 # Пребовляем к j  + 1 
    i = 1 # сбрасываем счётчик i на 1
print a 




--------------------
"Единственный способ изучать новый язык программирования - писать на нем 
программы." 
- Brian Kernighan

Remember, st1ng3r 
/server irc.ircline.ru /j #vingrad
PM   Вверх
Paranorma
Дата 19.1.2007, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 102
Регистрация: 1.1.2007

Репутация: 1
Всего: 1



Цитата(doomik @ 17.1.2007,  22:18)
Код

a = [45, 1, 34, 12, 78, 45, 12, 1, 34]
# 45 1 34 12 78
i = 1
j = 0
while j < (len(a))-1:
    while i < (len(a)):
        if a[j] == a[i] and j != i: # Делаем проверку если а елемент равен а + 1 и если i != j 
            del a[i] # Удаляем повторяющийся елемент
        i += 1  # Продвигаем счётчик на 1 шаг 
    j += 1 # Пребовляем к j  + 1 
    i = 1 # сбрасываем счётчик i на 1
print a 

Я эту программу немного изменила

Код

a = [45, 1, 34, 12, 1, 45, 45, 12, 1, 34]
i = 0
while i < len(a)-1:
    j = i+1
    while j < len(a):
        if a[i] == a[j]: 
            del a[j] 
        j = j + 1
    i = i+1
print a 


Она работает, но вот странно. У меня тут в списке трижды встречается число 45 и в калькуляторе и результат вот каким получается.

Код

[45, 1, 34, 12, 45]


Почему-то 45 все равно дважды встречается в списке. А вот что преподаватель написал в своем письме:

Другой вопрос разобрались ли вы во всех деталях
как это все работает ? 
Если разобрались то разбиритесь почему не работает
вот с таким списком a = [1, 1, 1]
Выполните программу в пошаговом режиме печатая содержимое 
списка после каждого шага.
Перед каждым шагом попытатесь угадать что получится
и сравните с тем что получилось. Особое внимание 
обратите на момент когда из списка удаляется элемент.
После того как разберетесь исправьте ошибку.


Я попробовала свой список заменить на a = [1, 1, 1] и печатается почему то 2 единицы вместо одной, т.е. удаляется один дубликат вместо двух.
Я попробовала все это выполнить в пошаговом режиме, но своей ошибки так и не увидела.
Что делать? Точнее в чем же здесь ошибка?

PM MAIL Skype Jabber MSN   Вверх
Void
Дата 19.1.2007, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 6
Всего: 173



Цитата(Paranorma @  19.1.2007,  21:57 Найти цитируемый пост)
Точнее в чем же здесь ошибка?

При удалении одного элемента все находящиеся за ним элементы списка сдвигаются. В результате счётчик «проскакивает» мимо следующего элемента.

Самое правильное решение: не изменять исходный список, а формировать на его основе новый. Потенциальных возможностей для ошибок куда меньше. (Поборникам производительности: взгляните на реализацию list и прикиньте, что происходит при выполнении del a[i]. А теперь сравните с затратами на создание нового списка.)

Если всё-таки сильно хочется остаться с текущим вариантом, то после удаления элемента не надо увеличивать счётчики.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
doomik
Дата 20.1.2007, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Одинокий волк
**


Профиль
Группа: Участник
Сообщений: 360
Регистрация: 25.10.2005
Где: #vingrad

Репутация: 3
Всего: 15



Тогда можно так:
Код

a = [45, 1, 34, 12, 78, 45, 12, 1, 34] 
# Вывод -> 45 1 34 12 78 
i = 1
j = 0
while j < len(a):
    while i < len(a):
        if a[j] == a[i] and j != i: # Если a[j] равно a[i] 
            a[i] = 'a' # Тогда a[i] получает 'a'
        i += 1  
    j += 1 
    i = 1
 
k = 0
aLen = len(a) # Сохраняем длинну списка 
while k < aLen: 
        if a[k] == 'a': # Если a[k] равно 'a'
                del a[k] # То удаляем a[k]
                aLen -= 1 # Меняем длинну листа на один меньше 
                k -= 1 # Меняем счётчик на один меньше
        k += 1 
print a 


Если есть 2 одинаковых елемента то второй преврощается в 'a' а дальше идёт проверка если есть в списке 'a' то удалить его.
Правда это будет работать если список состоит только из цифр, если список состоит из цифр и букв то наверное всётаки можно найти какой-небудь другое исключения.

Это сообщение отредактировал(а) doomik - 20.1.2007, 00:31


--------------------
"Единственный способ изучать новый язык программирования - писать на нем 
программы." 
- Brian Kernighan

Remember, st1ng3r 
/server irc.ircline.ru /j #vingrad
PM   Вверх
V.A.KeRneL
Дата 24.1.2007, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vadim A. Kazantsev
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 3.12.2006
Где: Moscow, Russia

Репутация: 7
Всего: 14



Вот моя «безопасная» (с созданием нового объекта-списка) функция: 
Код

def uniq(a):
    b = []
    i = 0
    while (i < len(a)):
        if (not b.__contains__(a[i])):
            b.append(a[i])
        i += 1
    return b


Пример использования функции: 
Код

>>> a = [1, 1, 1]
>>> b = uniq(a)
>>> a
[1, 1, 1]
>>> b
[1]



Это сообщение отредактировал(а) V.A.KeRneL - 24.1.2007, 18:52


--------------------
«C'est un pense-creux d'ici. C'est le meilleur et le plus irascible homme du monde...» © Ф.М. Достоевский, «Бесы»
---/)/)---(\.../)---(\(\
--(':'=)---(=';'=)---(=':')
(")(")..)-(").--.(")-(..(")(")

PM MAIL IM ICQ AOL YIM MSN   Вверх
Void
Дата 24.1.2007, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 6
Всего: 173



Цитата(V.A.KeRneL @  24.1.2007,  20:52 Найти цитируемый пост)
if (not b.__contains__(a[i])):

Это эквивалентно a[i] in b.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
V.A.KeRneL
  Дата 24.1.2007, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vadim A. Kazantsev
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 3.12.2006
Где: Moscow, Russia

Репутация: 7
Всего: 14



Цитата(Void @  24.1.2007, 19:05 Найти цитируемый пост)

Это эквивалентно a[i] in b.

Вернее 
if (not a[i] in b): 
smile

Интерактивную хелпу к Питону я уже научиля читать: 
Код

>>> help(a)
Help on list object:

class list(object)
 |  list() -> new list
 |  list(sequence) -> new list initialized from sequence's items
 |
 |  Methods defined here:
...
 |  __contains__(...)
 |      x.__contains__(y) <==> y in x
...


Но мне, тем не менее, больше нравится мой вариант с методом __contains__(...).


Это сообщение отредактировал(а) V.A.KeRneL - 24.1.2007, 19:44


--------------------
«C'est un pense-creux d'ici. C'est le meilleur et le plus irascible homme du monde...» © Ф.М. Достоевский, «Бесы»
---/)/)---(\.../)---(\(\
--(':'=)---(=';'=)---(=':')
(")(")..)-(").--.(")-(..(")(")

PM MAIL IM ICQ AOL YIM MSN   Вверх
Void
Дата 24.1.2007, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 6
Всего: 173



Цитата(V.A.KeRneL @  24.1.2007,  21:38 Найти цитируемый пост)
Но мне, тем не менее, больше нравится мой вариант с методом __contains__(...).

Зачем? Ну зачем усложнять жизнь себе и читающему код? По степени целесообразности для меня это эквивалентно (2).__add__(2) вместо 2 + 2 или a.__getitem__(i) вместо a[i].
В каждом языке есть определённые best practices. Им не стоит следовать догматично, но и ломать их только потому, что так хочется, не стоит. TIMTOWTDI must die smile


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
V.A.KeRneL
Дата 24.1.2007, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vadim A. Kazantsev
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 3.12.2006
Где: Moscow, Russia

Репутация: 7
Всего: 14



Void, я пришёл из Ruby... Вернее, я из него и не выходил!.. smile Вам это ни о чём не говорит?.. 
Ну тогда просто скажу, что я привык (на подсознательном уровне) использовать ключевое слово in в циклах, а не в условиях. 
В Паскале in используется в условиях (для проверки принадлежности элемента множеству (set)), но только в них! 
А в скриптовых языках Ruby и Python это зарезервированное слово используется для организации цикла for. И моё имхо, должно использоваться только для них, т.к. меня лично коробит использование одного и того же ключевого слова для организации совершенно разных конструкций. 
А плюс и квадратные скобочки, к счастью, ни с чем не конфликтуют, так что их я использовал, использую и буду использовать без малейшего дискофорта! smile

Цитата(Void @  24.1.2007, 19:50 Найти цитируемый пост)

TIMTOWTDI must die smile

В принципе, об этом я и написал выше, только более подробно. «Краткость — сестра таланта» © А.П. Чеховsmile

З.Ы. Но что-то мы заоффтопили... Пора бы Paranorma'е пометить вопрос решённым!


Это сообщение отредактировал(а) V.A.KeRneL - 24.1.2007, 21:05


--------------------
«C'est un pense-creux d'ici. C'est le meilleur et le plus irascible homme du monde...» © Ф.М. Достоевский, «Бесы»
---/)/)---(\.../)---(\(\
--(':'=)---(=';'=)---(=':')
(")(")..)-(").--.(")-(..(")(")

PM MAIL IM ICQ AOL YIM MSN   Вверх
Void
Дата 24.1.2007, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 6
Всего: 173



V.A.KeRneL, говорит, говорит.
Но всё-таки, фразу про устав и монастырь стоит иметь в виду smile
По мне неоднозначности тут нет. Да что я, это даже на сложность формальной грамматики не влияет smile Ну да оставим.
Цитата(V.A.KeRneL @  24.1.2007,  22:57 Найти цитируемый пост)
Но что-то мы заоффтопили

Есть немного. Если видно какое-то продолжение темы, то можно попросить модераторов отделить.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
pythonwin
Дата 25.1.2007, 07:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2529
Регистрация: 18.4.2006
Где: за компом

Репутация: нет
Всего: 36



Цитата(Void @  25.1.2007,  00:05 Найти цитируемый пост)
Но всё-таки, фразу про устав и монастырь стоит иметь в виду smile

программист == человек, и поэтому мыслит ассоциациями smile
Цитата(V.A.KeRneL @  24.1.2007,  23:57 Найти цитируемый пост)
т.к. меня лично коробит использование одного и того же ключевого слова для организации совершенно разных конструкций. 

я за использование in а условиях - в ФП бывает нужно сильно сократить код + увеличивается скорость выполнения
Цитата(V.A.KeRneL @  24.1.2007,  23:57 Найти цитируемый пост)
А плюс и квадратные скобочки, к счастью, ни с чем не конфликтуют, так что их я использовал, использую и буду использовать без малейшего дискофорта! smile

это ФП в python - говорят пришло из Lisp, но это лучше к Artemios или albertn.
позволяет сильно сократить код

Это сообщение отредактировал(а) pythonwin - 25.1.2007, 07:54
PM WWW GTalk Jabber   Вверх
Artemios
Дата 25.1.2007, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 405
Регистрация: 14.8.2006
Где: Саратов, Россия

Репутация: 2
Всего: 50



Цитата(pythonwin @  25.1.2007,  07:47 Найти цитируемый пост)
но это лучше к Artemios или albertn.

лучше к Void smile

in как in... Это ж не арифметический цикл.
while <condition1>: <actions>
for <condition2>: <actions> , где на condition2 наложено ограничение condition2= leftExpr in rightExpr, а for производит перебор элементов из rightExpr и их унификацию с leftExpr... Не знаю, может лучше было бы forall назвать, хотя здесь без разницы...


--------------------
fib = 1: 1: [ x+y | (x,y) <- zip fib (tail fib) ]
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0951 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.