C# le moyen le plus rapide pour changement de tableau
Comment puis-je basculer rapidement tous les éléments dans un tableau à gauche, rembourrage de la fin avec la valeur null?
Par exemple, [0,1,2,3,4,5,6] devient [1,2,3,4,5,6,null]
Edit: je l'ai dit rapidement, mais je suppose que je voulais dire de manière efficace. J'ai besoin de faire cela sans créer une Liste ou une autre structure de données. C'est quelque chose que j'ai besoin de faire plusieurs centaines de milliers de fois dans le plus court laps de temps que possible.
- ne devrait-elle pas être [1,2,3,4,5,6,null]
- Je voudrais être en mesure de faire sur n'importe quel indice, soit 0, 1 ou 4
- Pouvez-vous clearify rapide? Entendez-vous rapide en un minimum de lignes de code, ou plus rapide que dans la performance de la algorithim etc...
- Votre exemple ci-dessus n'est pas un "shift" - un changement implique la suppression du premier élément dans le tableau, vous êtes désireux de le retirer de tout indice.
- Si vous avez besoin de faire plusieurs centaines de milliers de fois, vous utilisez peut-être la mauvaise structure de données.
- Jimmy, Ce qui pourrait éventuellement être plus rapide qu'une discbased qui a compilateur instructions. Quelle structure de données dois-je utiliser. Je tiens également à préciser que ce tableau ne sera pas très long, jamais plus de 100 articles.
- il suffit d'utiliser une boucle for, comme suggéré ou d'un Tableau.Copie, rien ne devrait être plus rapide que celui
- Une file d'attente, en fait, être plus rapide qu'un tableau, le compilateur instructions nonobstant. Une file d'attente maintient de début et de fin des pointeurs, de sorte qu'il peut retirer l'élément premier (ou le dernier élément) en O(1) temps (par rapport à O(n) pour le tableau). Si les valeurs doivent être retirés du milieu, puis une liste liée serait mieux, mais alors que les changements de la complexité des autres opérations.
- Dested: Heh. "Ce qui pourrait éventuellement être plus rapide qu'un tableau?!"... Ainsi, une liste liée dans ce cas... Cependant, je vais jouer l'avocat du diable ici, et de se demander Si il n'y a qu'100 éléments dans le tableau, comment rapide est-il vraiment besoin de l'être? Est-ce votre application goulot d'étranglement?". Sauf si vous faites quelque chose de critique pour les performances, arrêtez de prendre soin. Et si vous faites quelque chose de critique pour les performances, puis nous allons voir quelques profiler les numéros s'il vous plaît?
- Sur votre exemple vous demander de déplacer les éléments d'un tableau. La réponse choisie, cependant, traite votre tableau comme immuables et en crée un nouveau... ce qui est plus lent en raison de l'appeler pour l'allocateur.
- LinkedList vous permet de jouer avec les deux extrémités de la collection avec la facilité. Pourrait être intéressant d'envisager la circulaire tableaux et les goûts.
Vous devez vous connecter pour publier un commentaire.
Voici mon test du harnais...
Voici les résultats de 1 million d'itérations de chaque solution (8 Core Intel Xeon E5450 @ 3.00 GHz)
Faire le choix pour vous-même 🙂
Array.Copy
gagne. Dang, c'est une méthode rapide.Buffer.BlockCopy
. Et @RobertDavis: page de manipulation de la table serait de fournir seulement une fraction de la capacité deArray.Copy
expose. Par exemple, elle nécessite d'alignement, n'ayant rien d'autre dans la même page, etc. Non,Array.Copy
est juste une copie en code natif avec une vérification de limites hissé en dehors de la boucle.Buffer.BlockCopy
est censé être plus optimisé de transfert, qui peut utiliser des trucs comme de l'ESS les charges et les magasins de déplacer plusieurs éléments à la fois.La plus rapide façon de le faire est d'utiliser
Array.Copy
, qui, dans la mise en œuvre finale utilise une mémoire de masse opération de transfert (similaire à memcpy):Édité: selon la documentation:
Donc, si vous ne voulez pas allouer un nouveau tableau, vous pouvez passer dans le tableau d'origine pour à la fois la source et la destination, bien que j'imagine que le compromis sera un peu plus lent de la performance car les valeurs de passer par un hébergement temporaire position.
Je suppose que, comme dans toute enquête de ce genre, vous devriez faire un peu rapide de l'analyse comparative.
Copy
méthode peut se chevauchent, de sorte que vous n'avez pas besoin de créer un autre tableau.Array.Copy(oldArray, 1, oldArray, 0, oldArray.Length - 1)
avec réglage le dernier élément ànull
fonctionnera également.for
boucle compile vers le bas dans le même maigre boucle traditionnelle memcpy les usages, qui ne sera pas le cas. Voir, par exemple, waldev.blogspot.com/2008/05/...Voici ma solution, similaire à la Tâche en ce que c'est un Tableau simple wrapper et qu'elle prend en O(1) temps de modifier le tableau à gauche.
Courant par Jason Punyon du code de test...
Faut ~29ms, quelle que soit la taille de la matrice.
Utiliser le
Array.Copy()
méthode que dansLa
Array.Copy
est probablement la façon, Microsoft a voulu nous faire copier des éléments d'un tableau...Ne pourriez-vous pas utiliser un Système.Les Collections.Génériques.File d'attente au lieu d'un tableau ?
Je sens que vous avez besoin pour effectuer des actions sur votre valeur le jeter, donc à l'aide d'une file d'attente semble plus approprié :
Si il absolument a d'être dans un tableau, alors je vous recommande la plus évidente de code possible.
Cela donne l'optimiseur le plus d'opportunités de trouver la meilleure façon de quelle que soit la plate-forme cible le programme est installé.
EDIT:
J'ai juste emprunté Jason Punyon du code de test, et j'ai peur qu'il a raison. Tableau.Copie gagne!
Tableau.Copie dure entre 103 et 150 ms sur ma machine.
pour la boucle prend entre 269 et 338 ms sur ma machine.
Pour toute verser de l'âme de trouver ce fil et sur le point de mettre en œuvre l'un des très bien notés réponses. Tous d'entre eux sont des ordures, je ne suis pas sûr pourquoi. Peut-être Dested demandé une nouvelle matrice de mise en œuvre au premier ou quelque chose qui a été retiré de la question. Eh bien tout simplement si vous souhaitez modifier le tableau et n'ont pas besoin d'un nouveau, de voir une réponse comme tdaines de réponse. Et de lire sur des choses comme la mémoire Tampon Circulaire /Anneau de la mémoire Tampon : http://en.wikipedia.org/wiki/Circular_buffer. Pas de déplacement des données réelles est nécessaire. La performance de déplacement d'un tableau doit pas être liée à la taille de la matrice.
Ne pouvez pas vous
allouer le tableau avec un supplément de 1000 éléments
avoir une variable de type entier
int base = 0
au lieu d'accéder à
a[i]
accèsa[base+i]
faire votre quart de travail, il suffit de dire
base++
Puis, après que vous avez fait 1000 fois, de la recopier et de recommencer.
De cette façon, vous ne faites la copie une fois par 1000 quarts de travail.
Vieille blague:
Q: Combien d'IBM 360 prend-il pour la maj d'un registre par 1 bit?
Un: 33. 32 pour contenir les bits à la place, et de 1 à déplacer le registre. (ou quelque chose du genre...)
Vous pouvez utiliser le même tableau que la source et la destination pour vite en place de copie:
Vous pouvez le faire comme ceci:
Bien sûr, il serait plus efficace de se débarrasser de la matrice entièrement et il suffit d'utiliser une Liste<>. Vous pouvez oublier la première ligne et la dernière ligne et de faire comme ceci:
Je sais que c'est une vieille question, mais venant de Google, il n'y a pas de simple exemple, grâce à ce est la façon la plus facile de réorganiser une liste, et vous n'avez pas à fournir le type il va s'en sortir, au moment de l'exécution,
Essayer cette! à l'aide de Linq. Pas besoin de deuxième Tableau.
De sortie:
[0,1,2,3,4,5,6] devient [1,2,3,4,5,6,null]
Si vous êtes propriétaire de la mémoire vous pouvez envisager d'utiliser Le Code Unsafe et de la bonne vieille pointeurs.
Assurez-vous d'un flux de mémoire et de verrouiller ou de l'utilisation
Marshal.AllocHGlobal
Construire tous vos tableaux avec un peu de rembourrage au début et à la fin.
d'incrémenter ou de décrémenter l'ensemble de la matrice de pointeurs à la fois. Vous aurez toujours besoin de boucle de retour et de définir vos valeurs null.
Si vous avez besoin de manière sélective incrémenter ou décrémenter les tableaux, vous devrez ajouter du rembourrage entre eux.
Les tableaux sont incroyablement faible niveau des structures de données, si vous les traiter dans un niveau bas façon, vous pouvez obtenir une énorme prestation.
Un baytrail cela peut surpasser de Jason avec toutes ses 8 Core Intel Xeon E5450 @ 3.00 GHz
Pas testé ce code, mais il devrait décale toutes les valeurs à droite par un. Notez que les trois dernières lignes de code est tout ce dont vous avez besoin pour efficacement maj du tableau.
Tableau de la copie est un O(n) fonctionnement et crée un nouveau tableau.
Tandis que la matrice de la copie peut certainement être fait rapidement et efficacement, le problème que vous avez dit peut effectivement être résolu d'une manière entièrement différente sans (comme vous l'avez demandé) la création d'un nouveau tableau/structure de données et seulement à la création d'un petit emballage de l'objet par exemple de tableau:
Par l'emballage et le contrôle de l'accès à la matrice de cette manière, nous pouvons maintenant démontrer la façon dont le problème a été résolu avec un O(1) appel de la méthode...
Produira la sortie:
Base de la matrice de: [ 0, 1, 2, 3, 4, 5, 6 ]
Décalé tableau: [ 0, 2, 3, 4, 5, 6, null ]
Je suis prêt à parier qu'il y aura une raison pour qu'une telle solution ne fonctionne pas pour vous, mais je crois que cela ne correspond pas à vos premiers besoins exprimés. 8 )
Il est souvent utile de réfléchir à toutes les différentes sortes de solutions à un problème avant de mettre en œuvre un spécifique, et peut-être que peut-être la chose la plus importante que cet exemple peut démontrer.
Espérons que cette aide!
Incorrect et légèrement amusant réponse (merci, je vais être ici toute la nuit !)
Dans l'esprit de toujours utiliser Skip (ne me demandez pas, je sais que le pire de l'utilisation de LINQ méthodes d'extension jamais), la seule façon que j'ai pensé de la réécriture, il serait
Mais elle n'est absolument PAS plus vite que les autres options.
ToArray
estToExpensive
.La meilleure et la plus efficace, je crois, à l'aide de la mémoire Tampon.BlockCopy fonction.
Vous définissez à la fois la source et la destination de votre tableau, le décalage de la source est de 1. En fonction de votre type de tableau (je suppose qu'il est de type int), 1 int = 4 octets, de sorte que vous devez passer en 4 comme deuxième paramètre de cette fonction. Notez que le décalage est de décalage d'octet.
De sorte qu'il ressemble à ceci:
Voir C# code ci-dessous pour le supprimer de l'espace de la chaîne. Ce changement de caractère dans le tableau. La Performance est O(n). Aucun autre tableau est utilisé. Donc pas de mémoire supplémentaire soit.