Piszę aplikację e-mail, która łączy się z bazą danych MySQL. Mam dwie tabele, które pobierają moje dane, z których jedna zawiera rezygnację z subskrypcji, a druga to standardowa tabela użytkowników. W tej chwili tworzę wektor wskaźników do obiektów e-mail i początkowo przechowuję w nim wszystkie niesubskrybowane e-maile. Mam wtedy standardową pętlę SQL, w której sprawdzam, czy e-mail nie znajduje się w wektorze anulowania, a następnie dodam go do globalnego wektora wysyłania wiadomości e-mail. Moje pytanie brzmi, czy istnieje skuteczniejszy sposób robienia tego? Muszę przeszukać wektor unsub dla każdego e-maila w moim systemie, do 50K różnych. Czy istnieje lepsza struktura do wyszukiwania? I lepszą strukturę do utrzymywania wyjątkowej kolekcji wartości? Być może taki, który po prostu odrzuciłby wartość, jeśli już to zawiera?Najszybszy kontener C++: Unikalne wartości
Odpowiedz
Jeśli implementacja biblioteki standardowej C++ ją obsługuje, należy rozważyć użycie std::unordered_set
lub std::hash_set
.
Można również użyć std::set
, choć narzut ten może być wyższy (zależy to od kosztu wygenerowania skrótu dla obiektu w porównaniu z kosztem porównywania dwóch obiektów kilka razy).
Jeśli używasz pojemnika na bazie węzła jak set
lub unordered_set
, można również uzyskać tę zaletę, że usuwanie elementów jest stosunkowo tani w porównaniu do usuwania ze vector
.
Myślę, że masz na myśli 'std :: unordered_set' lub' std :: tr1 :: unordered_set' –
Również 'std :: hash_set' nie jest częścią standardu, lepiej jest użyć' boost :: unordered_set', jeśli nie ma ani TR1, ani C++ 0x. –
@Evan: Masz rację; Miałem na myśli 'std :: unordered_set'. Dziś rano nie jadłem kawy. Większość implementacji biblioteki standardowej udostępnia 'hash_set' w takiej czy innej formie. –
Zapisz swoje adresy e-mail w numerze std::set
lub użyj std::set_difference()
.
+1 dla 'set_difference' (ponieważ jest upieczony), ale polecam używanie 3 (posortowanych) wektorów zamiast zestawów, ponieważ powinno być ich szybsze przechodzenie (lepsza lokalizacja pamięci). Alternatywnie, 'deque' może być również uznany, jeśli rozmiar jest duży i nie używasz Dirkumware (i jego małych segmentów). –
@Matthieu: Używając 'set_difference', użyjesz oczywiście posortowanych wektorów. Co jeszcze? –
tylko upewniając się, że :) kontenery oparte na węzłach mogą boleć wolno. –
Zadania tak (zestaw manipulacje) są lepiej pozostawić to, co ma na celu ich wykonania - baza danych!
E.g. coś wzdłuż linii:
SELECT email FROM all_emails_table e WHERE NOT EXISTS ( SELECT 1 FROM unsubscribed u where e.email=u.email )
Jeśli chcesz algorytm, można to zrobić szybko, pobierając zarówno listę e-maile i listy unsubscriptions as ordered list. Następnie możesz przejrzeć listę e-mail (która jest zamówiona), a kiedy to zrobisz, przesuniesz się wzdłuż listy wypisania. Chodzi o to, że przesuwasz o 1 do przodu, w zależności od tego, który element ma "największy" bieżący element.To algo to O (M + N) zamiast O (M * N), takie jak bieżące:
Lub, możesz wykonaj mapowanie hash, które odwzorowuje z niesubskrybowanego adresu e-mail na 1. Następnie wykonujesz wywołania
find()
na tej mapie, dla poprawnych implementacji hash są O (1) dla każdego wyszukiwania Niestety, nie ma standardu Hash Map w C++ - zobacz this SO question for existing implementations (kilka pomysłów istnieją SGI STL hash_map i doładowania i/lub TR1std::tr1::unordered_map
)Jedna z uwag dotyczących tego stanowiska wskazuje, zostanie on dodany do normy. „Mając to na uwadze, standardowa biblioteka Raport techniczny C++ wprowadzony nieuporządkowanego asocjacyjne pojemniki, które są realizowane z wykorzystaniem tabel mieszania, a one zostały dodane do projektu Roboczej C++ standard.”
Niestety, nie mogę tego zrobić w przypadku części mojego wniosku, ze względu na sposób, w jaki wcześniej przygotowano jedną z tabel. – Josh
@Josh: Czy zamieścisz odpowiednie części swojego schematu? Czy masz oddzielną tabelę dla niesubskrybowanych e-maili? –
Dlaczego nie używać 'LEFT OUTER JOIN'? 'SELECT \' email \ 'FROM \' all_emails_table \ 'AS \' e \ 'LEFT OUTER JOIN \' unsubscribed \ 'AS \' u \ 'ON \' e \ '. \' Email \ '= \' u \ '. \' email \ 'WHERE \' u \ '. \' email \ 'IS NULL;' –
Najlepszym sposobem, aby to zrobić jest w MySQL, myślę. Możesz zmodyfikować schemat tabeli użytkowników za pomocą innej kolumny, kolumna BIT
, ponieważ "nie jest subskrybowana". Co lepsze: dodaj kolumnę DATETIME
dla "data usunięta" z domyślną wartością NULL
.
Jeżeli stosując kolumnę BIT
, zapytanie będzie coś takiego:
SELECT * FROM `users` WHERE `unsubscribed` <> 0b1;
Jeżeli stosując kolumnę DATETIME
, zapytanie będzie coś takiego:
SELECT * FROM `users` WHERE `date_unsubscribed` IS NULL;
Ponadto, teraz rezygnujesz z subskrypcji użytkowników. Aktualny schemat anuluje adresy e-mail, co nie jest dokładnie tym samym. Jeśli użytkownik zmieni swój adres e-mail na taki, który nie jest subskrybowany, czy powinien przestać otrzymywać wiadomości? Podejście OP mówi "tak", to mówi "nie", co, jak sądzę, jest bardziej prawdopodobne, że jest właściwą odpowiedzią. –
- 1. Jaki kontener przechowywać wartości unikatowe?
- 2. PHP Array unikalne wartości
- 3. Najszybszy sposób określania wartości na podstawie wartości boolowskiej C++
- 4. Standardowy kontener C++ i kontener STL w C++
- 5. Kontener kowariancji w C++
- 6. Policz unikalne wartości w Excelu
- 7. Unikalne wartości tablic w Mongoose
- 8. Oblicz unikalne wartości z warunkiem
- 9. Najszybszy kontener lub algorytm dla unikalnych identyfikatorów wielokrotnego użytku w C++
- 10. IoC kontener dla Objective-C
- 11. Kontener, w którym wartości wygasają w pythonie
- 12. php coraz unikalne wartości z tablicy wielowymiarowej
- 13. Jak uzyskać unikalne wartości na liście
- 14. znalezienie unikalne wartości w pliku danych
- 15. jsp kontener kontra kontener serwletu
- 16. Najszybszy sposób komunikacji między C++ i C#
- 17. Zmienny kontener z niezmiennymi obiektami w C++
- 18. Uzyskaj unikalne wartości na liście list w pythonie
- 19. Uzyskaj unikalne identyfikatory systemu w języku C#
- 20. Uzyskaj unikalne wartości z kolumny indeksu w MultiIndex
- 21. Ogólny kontener dla wielu typów danych w C++
- 22. C++ najszybszy sposób wyczyszczenia lub usunięcia wektora
- 23. Najszybszy sygnał C++ sygnału/gniazda bez zależności
- 24. Jak uzyskać tabelę zlicza unikalne wartości w kolumnie
- 25. Zapytanie o wszystkie unikalne wartości pola za pomocą Elasticsearch
- 26. Jak wybrać unikalne wartości w d3.js z danych
- 27. Jak mogę uzyskać unikalne wartości w tablicy w zapytaniu jmespath?
- 28. Zapytanie SQL określające, że wartości w kolumnie są unikalne.
- 29. Angular UI Select, Unikalne wartości wstępnie wybrana tablica
- 30. Python unikalne tworzenie ciągów
DVK i Daniel Trebbien rację: to prawie na pewno lepiej to zrobić w DB. Nie wierzę ci, gdy mówisz, że to niemożliwe - opublikuj odpowiednie części schematu. –
dlaczego generowanie wiadomości e-mail przed sprawdzeniem, czy użytkownik chce je otrzymywać? Robisz dodatkową robotę tutaj ... –
@Matthieu: Nie generuję treści e-mailowych, zbieram adresy e-mail do odsyłaczy. – Josh