Tarkim, noriu sąraše palikti tik po vieną reikšmę, ištrindamas pasikartojančias:
raides = ['a', 'c', 'a', 'a', 'k', 'o', 'l', 'b', 't', 'a', 'f', 'k', 'y', 'a', 'b', 'm', 'a']
for j in raides:
if raides.count(j) > 1:
raides.remove(j)
print raides
# lyg ir veikia:
>>>['c', 'o', 'l', 't', 'f', 'k', 'y', 'b', 'm', 'a']
Bet jeigu sąraše skaičiai, nebeveikia. Ištrina tik kas antrą pasikartojantį skaičių ar kažkas panašaus:
skaiciai = [1, 2, 4, 1, 2, 5, 1, 6, 8, 1, 2, 5, 2, 3, 4, 8, 3, 5]
for i in skaiciai:
if skaiciai.count(i) >1:
skaiciai.remove(i)
print skaiciai
>>>[5, 1, 6, 1, 5, 2, 4, 8, 3, 5]
Skaitinėju tekstus pradinukams, ir kai jau pradedu galvoti, kad kažką išmokau, Pythonas pasišaipo:). Ne tiek įdomu kaip reikėtų spręsti tokią užduotį, bet norėtųsi sužinot kas čia daros su tais skaičiais.
Būčiau dėkingas ir už pasiuntimą į konkrečią vietą - t.y. kur pasiskaitęs suprasčiau kame čia bėda:)
Savo pavyzdžiuose modifikuoji sąrašą, per kurį suki ciklą, tai reiškia, sąrašas trumpėja, o sąrašo kursorius elementus ima iš eilės ir praleidžia tuos, kurie pasislinko per vieną atgal dėl einamojo elemento ištrynimo.
Trumpiau tariant, geriau niekada nekeisk sąrašo, per kurį suki ciklą, nebent žinai ką darai.
Jie nori pašalinti besidubliuojančias reikšmes, reikia naudoti aibes (set()):
Labai dėkui už vargą.
Iš pradžių - su skaičiais - buvau apie tai pagalvojęs. Bet kai pabandžiau su raidėm, tada jau ta gyvatė pradėjo ėst smegenis.
Juk turėtų ištrint kas antrą, bet
raides = ['a', 'a', 'a', 'a', 'a', 'a', 'lept', 'k', 'a', 'a', 'a', 'a', 'a']
>>> ['lept', 'k', 'a', 'a', 'a', 'a', 'a'] # istrina visas pirmas 6 "a"
Tokiose situacijos visada galima pasitelkti debugerį ir išsiaiškinti, kame problema.
Debugerį galima paleisti į kodą įrašius tokią eilutę:
import pdb; pdb.set_trace()
Tarkim pilnas kodo pavyzdys būtų toks:
raides = ['a', 'a', 'a', 'a', 'a', 'a', 'lept',
'k', 'a', 'a', 'a', 'a', 'a']
import pdb; pdb.set_trace()
for j in raides:
if raides.count(j) > 1:
raides.remove(j)
Tada debuginimas vyksta taip:
> python skaiciai.py
> /tmp/skaiciai.py(4)<module>()
-> for j in raides:
(Pdb) help
Documented commands (type help <topic>):
========================================
EOF bt cont enable jump pp run unt
a c continue exit l q s until
alias cl d h list quit step up
args clear debug help n r tbreak w
b commands disable ignore next restart u whatis
break condition down j p return unalias where
Miscellaneous help topics:
==========================
exec pdb
Undocumented commands:
======================
retval rv
(Pdb) help p
p expression
Print the value of the expression.
(Pdb) p raides
['a', 'a', 'a', 'a', 'a', 'a', 'lept', 'k', 'a', 'a', 'a', 'a', 'a']
(Pdb) l
1 raides = ['a', 'a', 'a', 'a', 'a', 'a', 'lept',
2 'k', 'a', 'a', 'a', 'a', 'a']
3 import pdb; pdb.set_trace()
4 -> for j in raides:
5 if raides.count(j) > 1:
6 raides.remove(j)
[EOF]
(Pdb) n
> /tmp/skaiciai.py(5)<module>()
-> if raides.count(j) > 1:
(Pdb) p j
'a'
(Pdb) l
1 raides = ['a', 'a', 'a', 'a', 'a', 'a', 'lept',
2 'k', 'a', 'a', 'a', 'a', 'a']
3 import pdb; pdb.set_trace()
4 for j in raides:
5 -> if raides.count(j) > 1:
6 raides.remove(j)
[EOF]
(Pdb) tbreak 5, j != 'a'
Breakpoint 1 at /tmp/skaiciai.py:5
(Pdb) c
Deleted breakpoint 1
> /tmp/skaiciai.py(5)<module>()
-> if raides.count(j) > 1:
(Pdb) p j, raides
('lept', ['a', 'a', 'a', 'lept', 'k', 'a', 'a', 'a', 'a', 'a'])
(Pdb) b 5
Breakpoint 2 at /tmp/skaiciai.py:5
(Pdb) c
> /tmp/skaiciai.py(5)<module>()
-> if raides.count(j) > 1:
(Pdb) c
> /tmp/skaiciai.py(5)<module>()
-> if raides.count(j) > 1:
(Pdb) p j, raides
('a', ['a', 'a', 'a', 'lept', 'k', 'a', 'a', 'a', 'a', 'a'])
(Pdb) c
> /tmp/skaiciai.py(5)<module>()
-> if raides.count(j) > 1:
(Pdb) p j, raides
('a', ['a', 'a', 'lept', 'k', 'a', 'a', 'a', 'a', 'a'])
Iš viso šito matosi labai aiškus atsakymas, cikle sąrašas modifikuojamas, todėl kiekvieną kartą ištrynus vieną elementą sąrašas sutrumpėja, visi elementai pasislenka į pradžią, todėl visą laiką ištrynus vienas elementas yra praleidžiamas. Todėl prasisukus per visus 6 pasikartojančius 'a' sąrašo elementus, trys ištrinami, trys lieka. Toliau situacija vėl kartojasi, sąrašo pabaigoje yra 5 pasikartojantys 'a' elementai, iš kurių bus ištrintas tik kas antras, todėl nuo pradžios vėl nutrinami trys 'a' elementai, o visi kiti lieka.
Dar kartą pasikartosiu negalima keisti sąrašo, per kurį sukamas ciklas. Keisti gali tik tuo atveju, jei tiksliai žinai ką darai, bet net ir tuo atveju, kodas bus sunkiai suprantamas.
Pradžioj savo listą paverti į set'ą, set'as ištrina pasikartojančias reikšmes, paskui paverti atgal į listą... Tik verčiant į set'ą, eilės tvarka yra neišlaikoma. Jei reikia eiliškumą išlaikyti, naudok sirex pasiūlytą variantą su generatoriais.
Tarkim, noriu sąraše palikti tik po vieną reikšmę, ištrindamas pasikartojančias:
Bet jeigu sąraše skaičiai, nebeveikia. Ištrina tik kas antrą pasikartojantį skaičių ar kažkas panašaus:
Skaitinėju tekstus pradinukams, ir kai jau pradedu galvoti, kad kažką išmokau, Pythonas pasišaipo:). Ne tiek įdomu kaip reikėtų spręsti tokią užduotį, bet norėtųsi sužinot kas čia daros su tais skaičiais.
Būčiau dėkingas ir už pasiuntimą į konkrečią vietą - t.y. kur pasiskaitęs suprasčiau kame čia bėda:)
Savo pavyzdžiuose modifikuoji sąrašą, per kurį suki ciklą, tai reiškia, sąrašas trumpėja, o sąrašo kursorius elementus ima iš eilės ir praleidžia tuos, kurie pasislinko per vieną atgal dėl einamojo elemento ištrynimo.
Trumpiau tariant, geriau niekada nekeisk sąrašo, per kurį suki ciklą, nebent žinai ką darai.
Jie nori pašalinti besidubliuojančias reikšmes, reikia naudoti aibes (set()):
Jei dėl kokių nors priežasčių netinka set(), visada rekomenduojamas būdas apdoroti sąrašus yra kuriant kitą sąrašo kopiją:
Dar vienas variantas dėl sąrašų apdorojimo yra taip vadinami generatoriai.
Tavo pavyzdį su generatoriais būtų galima perrašyti taip:
Labai dėkui už vargą.
Iš pradžių - su skaičiais - buvau apie tai pagalvojęs. Bet kai pabandžiau su raidėm, tada jau ta gyvatė pradėjo ėst smegenis.
Juk turėtų ištrint kas antrą, bet
Tokiose situacijos visada galima pasitelkti debugerį ir išsiaiškinti, kame problema.
Debugerį galima paleisti į kodą įrašius tokią eilutę:
Tarkim pilnas kodo pavyzdys būtų toks:
Tada debuginimas vyksta taip:
Iš viso šito matosi labai aiškus atsakymas, cikle sąrašas modifikuojamas, todėl kiekvieną kartą ištrynus vieną elementą sąrašas sutrumpėja, visi elementai pasislenka į pradžią, todėl visą laiką ištrynus vienas elementas yra praleidžiamas. Todėl prasisukus per visus 6 pasikartojančius 'a' sąrašo elementus, trys ištrinami, trys lieka. Toliau situacija vėl kartojasi, sąrašo pabaigoje yra 5 pasikartojantys 'a' elementai, iš kurių bus ištrintas tik kas antras, todėl nuo pradžios vėl nutrinami trys 'a' elementai, o visi kiti lieka.
Dar kartą pasikartosiu negalima keisti sąrašo, per kurį sukamas ciklas. Keisti gali tik tuo atveju, jei tiksliai žinai ką darai, bet net ir tuo atveju, kodas bus sunkiai suprantamas.
O kai kuriems ko gero bus ir visai nesuprantamas;)
Dar kartą dėkui.
Naudok set'us ir bus labai aiškus kodas:
Pradžioj savo listą paverti į set'ą, set'as ištrina pasikartojančias reikšmes, paskui paverti atgal į listą... Tik verčiant į set'ą, eilės tvarka yra neišlaikoma. Jei reikia eiliškumą išlaikyti, naudok sirex pasiūlytą variantą su generatoriais.
Dėkui.
Labai tikiuosi, kad jūsų pastangos neprapuls veltui:)
Tema perkelta iš https://legacy.ubuntu.lt/forum/viewtopic.php?f=11&t=7000