comment trouver les doublons dans std::vector<string>, et de renvoyer une liste d'entre eux?
Donc, si j'ai un vecteur de mots comme:
Vec1 = "words", "words", "are", "fun", "fun"
liste: "plaisir", "les mots"
Je suis en train d'essayer de déterminer quels sont les mots dupliqués, et retourne un vecteur par ordre alphabétique de 1 exemplaire. Mon problème est que je ne sais même pas par où commencer, la seule chose proche de ce que j'ai trouvé était std::unique_copy
qui n'est pas exactement ce dont j'ai besoin. Et plus précisément, je suis saisie d'un std::vector<std::string>
mais la sortie d'un std::list<std::string>
. Et si besoin, je peux utiliser foncteur.
Quelqu'un pourrait au moins me pousser dans la bonne direction s'il vous plaît? J'ai déjà essayé de lecture stl de la documentation,mais je suis juste "cerveau" bouché en ce moment.
std::set
pour stocker vos mots au lieu d'un vecteur vous obtenez l'unicité et le tri jeté dans pour gratuit.Puisque vous le voulez (en ordre alphabétique), je suppose que vous ne me dérangerait pas si il a été trié?
eh bien, je peux en faire une copie, puis à les trier, oui
puis, je me "sont" dans le résultat, ce qui n'est pas ce dont j'ai besoin
Pas tout à fait "gratuitement" ; -)), Il est plus lente conteneur.
OriginalL'auteur Marina Golubtsova | 2013-07-27
Vous devez vous connecter pour publier un commentaire.
std::unordered_set<std::string>
Puisque vous voulez chaque double seulement une fois que dans les résultats, vous pouvez utiliser un hashset (pas de liste) pour les résultats.
set
est une idée horrible (mauvais rendement).set
est pour lorsque vous insérez dynamique, qui vous n'avez pas besoin ici. Donc, justesort
lavector
et l'utilisationunique()
.il l'habitude de faire la tâche qu'il doit faire, qui est de compter les doublons, de ne pas faire le vecteur sans doublons
Je pensais que le fait d'appeler
unique
une fois pour supprimer les valeurs uniques vous quitterait avec des doublons; appelunique
de nouveau sur supprimer les doublons de ceux-ci, vous donnant le résultat que vous avez besoin. Cependant, il semble queunique
en fait détruit le reste de la matrice, de sorte que vous auriez besoin de modifier un peu les choses pour le faire fonctionner. Vous n'avez toujours pas besoin deset
, cependant.Voir ma réponse ci-dessous.
Cela dépend de la taille de l'entrée. Ma solution asymptotique de la performance est bien meilleure que le tri.
OriginalL'auteur Ben Voigt
De l'OMI, Ben Voigt a commencé avec une bonne idée de base, mais je vous déconseille de prendre sa formulation trop littéralement.
En particulier, je n'aime pas l'idée de chercher une chaîne de caractères dans le jeu, puis de l'ajouter à votre jeu si il n'est pas présent, et en l'ajoutant à la sortie si les, il était présent. Cela signifie essentiellement que chaque fois que nous les rencontrons un nouveau mot, nous sommes la recherche de notre ensemble de mots existants, une fois pour vérifier si un mot est présent, et à nouveau à insérer parce qu'il ne l'était pas. La plupart de cette recherche sera essentiellement identiques, à moins qu'un autre thread mutation de la structure dans l'intervalle (ce qui pourrait donner une race condition).
Au lieu de cela, j'aimerais commencer par essayer de l'ajouter à l'ensemble des mots que vous avez vu. Qui renvoie un
pair<iterator, bool>
, avec labool
ensemble detrue
si et seulement si la valeur a été inséré -- c'est à dire, ne l'a pas déjà présent. Qui nous permet de consolider la recherche d'une chaîne existante et de l'insertion de la nouvelle chaîne de caractères en un seul insert:Ce nettoie également le débit suffisant qu'il est assez facile de transformer l'essai en un foncteur que nous pouvons ensuite utiliser avec
std::remove_copy_if
pour produire nos résultats assez directement:En fonction de si je m'en souciais plus sur la simplicité du code ou de la vitesse d'exécution, je pourrais utiliser un
std::vector
au lieu de laset
pour le résultat, et l'utilisationstd::sort
suivie parstd::unique_copy
pour produire le résultat final. Dans un tel cas, je serais probablement aussi remplacer lestd::set
à l'intérieur deshow_copies
avec unstd::unordered_set
à la place:C'est un peu plus complexe (une ligne entière de plus!) mais probablement beaucoup plus vite quand/si le nombre de mots devient très grande. Notez également que je suis en utilisant
std::unique_copy
principalement pour produire visible de sortie. Si vous voulez juste le résultat dans une collection, vous pouvez utiliser le standard unique/effacement de l'idiome à obtenir des éléments uniques dansintermediate
.Eh bien oui, vous utilisez le test-si-il-est-présent-et-make-it-présent de l'opération. Ma réponse était destinée à être un guide, pas un mappage 1:1 pour les appels de fonction membre. Vous ne pouvez pas dire que j'ai choisi mauvaises méthodes pour plus de détails, quand je n'ai pas donner de détails. Et
existing
devrait probablement être ununordered_set
.Tout possible de comptage pour cette solution?
Je ne suis pas sûr exactement ce que vous demandez. Si vous voulez une liste de mots uniques, et un décompte de chaque, vous devez généralement utiliser un
map<string, int>
. Lire les mots et incrémenter le compteur pour chaque. Puis à pied à travers la carte et d'écrire les mots et le nombre de chaque.OriginalL'auteur Jerry Coffin
En 3 lignes (sans compter le vecteur et la création d'une liste ni le superflu des sauts de lignes dans le nom de la lisibilité):
MODIFIER
Explication de la solution:
Trier le vecteur est nécessaire pour utiliser
set_difference()
plus tard.La
uvec
jeu sera automatiquement vos éléments triés, et d'éliminer les doublons.La
output
liste sera complétée par les éléments devec - uvec
.Je ne suis pas sûr de bien vous comprendre.
OriginalL'auteur DanielKO
En place (pas d'espace de stockage supplémentaire). Aucune chaîne de la copie (à l'exception de la liste des résultats). Un tri + un pass:
OriginalL'auteur Leonid Volnitsky
Vous pouvez obtenir une assez propre mise en œuvre à l'aide d'un std::map pour compter les occurrences, puis en s'appuyant sur std::list::trier pour trier la liste de mots. Par exemple:
À l'aide d'un std::map il me semble un peu inutile, mais il fait le travail.
OriginalL'auteur Ethan Kaminski
Voici un meilleur algorithme que celles d'autres personnes ont proposé:
C'est mieux, car il ne nécessite
swap
sans auxiliairevector
pour le stockage, ce qui signifie qu'il se comporte de façon optimale pour des versions antérieures de C++, et il ne nécessite pas d'éléments pour être copiable.Si vous êtes plus intelligent, je pense que vous pouvez éviter le tri le vecteur à deux reprises.
O(N lg N)
complexité lorsqu'unO(N)
solution existe, c'est mieux?performance asymptotique, (2) performance empirique, (3) les exigences imposées à l'appelant (par exemple, pas besoin de copier les constructeurs, à l'exception de sécurité), (4) la nécessité pour les auxiliaires de la mémoire (la mienne n'a pas besoin de stocker des copies de l'entrée). Dans tous les cas, votre solution utilise également
set
, il est doncO(N log N)
trop, sauf queset
a bien pire performance empirique quevector
, rendant cette solution meilleure.OriginalL'auteur Mehrdad