acha, z tym "Co napiszesz działa tak jak oczekujesz" to chodzi bardziej o to, że ideę algorytmu, tak jak go rozmumiemy i tak jak jest w pseudokodzie, można w Pythonie łatwo zapisać.
Ok, to jest argument bardzo często podnoszony jako zaleta języków skryptowych (nie tylko Pythona). Że można szybko i prosto napisać, i że wygląda prawie jak pseudokod.
Zobaczmy jak to wyglądało w projekcie, w którym ostatnio jestem. Musiałem wywalić duplikaty z listy. Oczywiście nikt takich rzeczy nie pisze od zera. Np. w Scali zrobiłbym to tak:
Kopiuj
val list = List(1,5,2,1,2)
val newList = list.distinct
W "niskopoziomowym" Rust jest troszkę więcej ceregieli, bo trzeba przekształcić w iterator i z powrotem, bo tak jest uniwersalniej:
Kopiuj
use itertools::Itertools;
let list = vec![1,5,2,1,2];
let new_list: Vec<_> = list.into_iter().unique().collect();
A jeśli lista byłaby posortowana, to można użyć specjalistycznego dedup() które działa bez alokacji na stercie i jest bardziej cache-friendly:
Kopiuj
let list = vec![1,1,2,2,5];
let new_list: Vec<_> = list.into_iter().dedup().collect();
No i szczerze w Pythonie spodziewałem się czegoś podobnego.
Najpierw rzut okiem na listę metod dla listy:
dedup
? nie ma
unique
? nie ma
distinct
? nie ma
remove_duplicates
? nie ma
Mogę zrobić zbiór przez set()
, ale stracę kolejność...
Skończyły mi się pomysły, rzut oka w dokumentację. Nie ma nic.
Chwilka, wiem, przecież w Pytonie jest jeszcze itertools - iteratory na sterydach! Dokumentacja itertools:
powtarzanie elementu, nie to nie to ...
grupowanie, no może jakoś by się dało, ale strasznie naokoło...
kombinacje, permutacje, nie to też nie to,
parzenie kawy i herbaty... no nie, to też nie teraz...
koniec listy
Dobra, poddaję się, idę na StackOverflow.
Tamże najwyżej punktowana odpowiedź (serio?!):
Kopiuj
for i in mylist:
if i not in newlist:
newlist.append(i)
No dobra, ale to jest O(n^2) myślę sobie, musi być coś lepszego. Kawałek niżej jest:
Kopiuj
seen = {}
new_list = [seen.setdefault(x, x) for x in my_list if x not in seen]
Ostatecznie można też przez bezpośrednią konwersję do zbioru o ile się weźmie OrderedDict:
Kopiuj
from collections import OrderedDict
list(OrderedDict.fromkeys(lseparatedOrbList))
To jest akceptowalne, ale nadal bardzo "nie-wprost", bo deduplikacja jest tylko efektem ubocznym działania zbioru. A ja zbioru w ogóle nie potrzebowałem.
To tyle w kwestii tej słynnej czytelności i ekspresywności. Polega ona chyba na pisaniu od zera oczywistych rzeczy, a "batteries-included" to jedynie mit.
Może względem C i Javy się broni, ale serio inne języki poszły do przodu.
BTW: Żeby nie było, że się przyczepiłem tylko przez przypadek jednej rzeczy. Kolejna rzecz, która wydaje się serio na maksa podstawowa a jej nie ma, to znalezienie pierwszego elementu na liście, który spełnia warunek. Czyli coś co w wielu językach jest pod postacią metody lub funkcji find()
. A w Pythonie... nie ma. No, po prostu, musisz napisać sobie sam:
https://stackoverflow.com/questions/2361426/get-the-first-item-from-an-iterable-that-matches-a-condition