Vérifier si une valeur est dans un tableau (C #)

109

Comment vérifier si une valeur est dans un tableau en C #?

Comme, je veux créer un tableau avec une liste de noms d'imprimantes.

Celles-ci seront transmises à une méthode, qui examinera chaque chaîne tour à tour, et si la chaîne est identique à une valeur dans un tableau, effectuez cette action.

Par exemple:

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
foreach (p in printer)
{
   PrinterSetup(p);     
}

Ce sont les noms des imprimantes, ils sont alimentés par la méthode PrinterSetup.

PrinterSetup ressemblera à ceci (un pseudocode):

public void PrinterSetup(printer)
{
   if (printer == "jupiter") 
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

Comment formater if (printer == "jupiter")d'une manière que C # peut reconnaître?

Cecil Rodriguez
la source
4
Essayez de donner un type (chaîne) à votre nom de paramètre et tout ira bien.
Jon Skeet
2
Je suis un peu confus quant à la question. Vous demandez-vous comment vérifier si une valeur est dans un tableau ou comment faire une comparaison de chaînes en C #? Si c'est ce dernier, vous utiliseriez printer.Equals("jupiter"). Si c'est l'ancien, utilisez linqetprinter.Contains("jupiter")
newfurniturey
@newfurniturey Tout à fait ... la question est confuse, le code d'exemple ne correspond pas au titre, et donc les réponses sont également confuses; pourquoi la merde comme celle-ci est votée est au-delà de moi. Et il n'y a pas besoin de faire printer.Equals("jupiter")... Le code de l'OP if (printer == "jupiter")fonctionne très bien ... tant qu'il printerest déclaré être une chaîne, comme le note Skeet.
Jim Balter

Réponses:

231

Ajouter l'espace de noms nécessaire

using System.Linq;

Ensuite, vous pouvez utiliser la Contains()méthode linq

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}
Dmytro
la source
2
@ 0A0D. Cette réponse est, à mon avis, la meilleure solution en tant que moyen le plus simple / le plus court et le plus connu pour atteindre la même chose ( How do I check if a value is in an array in C#?) et aussi efficace. Pas de boucle, pas de méthode supplémentaire. Juste un espace de noms est supplémentaire, ce qui n'est pas une grande chose.
Sami
6
@Sami: Linq utilise des boucles en interne.
2
@ 0A0D Sam fait probablement référence à du code écrit, pas à des instructions compilées. Linq utilise des boucles et des méthodes en interne, mais du point de vue des codeurs, tout ce qui est caché et n'a pas besoin de s'inquiéter.
Trisped
1
Droite @ 0A0D. Je voulais dire que le codeur / développeur n'avait pas besoin de faire une boucle droite. La vérification hors parcours du tableau nécessite une boucle :)
Sami
3
C'est certainement facile et recommandable. Si vous n'avez pas accès à Linq, ou ne souhaitez pas utiliser Linq, vous pouvez vous fier à une implémentation d'interface explicite du tableau. Depuis .NET 1.1, nous avons ((IList)printer).Contains("Jupiter")ce qui est non générique (peut boxer les types de valeur, etc.) et fonctionne même pour les tableaux multidimensionnels. Et depuis .NET 2.0, nous avons le plus magique ((IList<string>)printer).Contains("Jupiter")qui est le plus sûr de type. L'approche Linq était nouvelle dans .NET 3.5.
Jeppe Stig Nielsen
29
   string[] array = { "cat", "dot", "perls" };

// Use Array.Exists in different ways.
bool a = Array.Exists(array, element => element == "perls");
bool b = Array.Exists(array, element => element == "python");
bool c = Array.Exists(array, element => element.StartsWith("d"));
bool d = Array.Exists(array, element => element.StartsWith("x"));

// Display bools.
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
----------------------------output-----------------------------------

1) Vrai 2) Faux 3) Vrai 4) Faux


la source
6
Cela devrait être la réponse acceptée. Si vous utilisez une baie, il n'est pas totalement improbable que les performances soient importantes. Dans ce cas, Linq est souvent le mauvais choix.
Philm
22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  
Client
la source
Ceci est un exemple général - pouvez-vous en fournir un qui correspond mieux à la question?
kaz
9
C'est peut-être un exemple général, mais c'est exactement ce que je cherchais.
Grant Birchmeier
7

Quelque chose comme ça?

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
PrinterSetup(printer);

// redefine PrinterSetup this way:
public void PrinterSetup(string[] printer)
{
    foreach (p in printer.Where(c => c == "jupiter"))
    {
        Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
    }
}
code4life
la source
7
    public static bool Contains(Array a, object val)
    {
        return Array.IndexOf(a, val) != -1;
    }
Raz Megrelidze
la source
2
J'aime ça. Cependant, il échouera s'il as'agit d'un tableau multidimensionnel (comme new string[10, 20, 15]par exemple), avec une exception. Il échouera également avec des tableaux unidimensionnels qui ne sont pas indexés à partir de zéro (comme Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, }), rare en C #, je l'admets), avec une valeur de retour éventuellement incorrecte. Ces lacunes sont faciles à corriger avec des génériques:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen
J'aime ça, mais seulement parce que c'est sans Linq et que cela confirme qu'IndexOf est la seule chose qui reste à utiliser.
Bitterblue
6

Remarque: la question concerne les tableaux de chaînes. Les routines mentionnées ne doivent pas être mélangées avec la méthode .Contains des chaînes simples.

Je voudrais ajouter une réponse étendue faisant référence à différentes versions de C # et pour deux raisons:

  • La réponse acceptée nécessite Linq qui est parfaitement idiomatique C # alors qu'il n'est pas gratuit et n'est pas disponible en C # 2.0 ou inférieur. Lorsqu'un tableau est impliqué, les performances peuvent être importantes, il existe donc des situations dans lesquelles vous souhaitez rester avec les méthodes Array.

  • Aucune réponse ne répond directement à la question où il a également été demandé de mettre cela dans une fonction (comme certaines réponses mélangent également des chaînes avec des tableaux de chaînes, ce n'est pas complètement sans importance).

Array.Exists () est une méthode C # /. NET 2.0 et n'a pas besoin de Linq. La recherche dans les tableaux est O (n). Pour un accès encore plus rapide, utilisez HashSet ou des collections similaires.

Depuis .NET 3.5, il existe également une méthode générique Array<T>.Exists():

public void PrinterSetup(string[] printer)
{
   if (Array.Exists(printer, x => x == "jupiter"))
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

Vous pouvez écrire une propre méthode d'extension (C # 3.0 et supérieur) pour ajouter le sucre syntaxique pour obtenir le même / similaire ".Contains" que pour les chaînes de tous les tableaux sans inclure Linq:

// Using the generic extension method below as requested.
public void PrinterSetup(string[] printer)
{
   if (printer.ArrayContains("jupiter"))
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

public static bool ArrayContains<T>(this T[] thisArray, T searchElement)
{
   // If you want this to find "null" values, you could change the code here
   return Array.Exists<T>(thisArray, x => x.Equals(searchElement));
}

Dans ce cas, cette ArrayContains()méthode est utilisée et non la méthode Contains de Linq.

Les méthodes .Contains mentionnées ailleurs font référence à List<T>.Contains(depuis C # 2.0) ou ArrayList.Contains(depuis C # 1.1), mais pas aux tableaux lui-même directement.

Philm
la source
1
Je suggère de changer le nom en ArrayContains () pour éviter toute confusion avec Linq Contains ()
peter.cyc le
Je l'ai fait, bien qu'il y ait aussi des arguments contre: C'est l'idée de base du polymorphisme d'utiliser le même nom pour différents types de données, en particulier avec un réglage Linq à l'esprit. Utiliser des noms différents n'est pas polymorphe. Mais la lisibilité et éviter les malentendus gagneront, je pense, donc, oui.
Philm le
4

Il vous manque juste quelque chose dans votre méthode:

public void PrinterSetup(string printer)
{
   if (printer == "jupiter") 
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
   }
}

Ajoutez simplement stringet tout ira bien.


la source
3

Le problème n'est pas très clair, mais il semble que vous vouliez quelque chose comme ceci:

    List<string> printer = new List<string>( new [] { "jupiter", "neptune", "pangea", "mercury", "sonic" } );

    if( printer.Exists( p => p.Equals( "jupiter" ) ) )
    {
        ...
    }
Brandon Moretz
la source
2

Envisagez d'utiliser HashSet<T>Class pour des raisons de performances de recherche:

Cette méthode est une opération O (1).

- HashSet<T>.ContainsMéthode (T), MSDN .

Par exemple:

class PrinterInstaller
{
    private static readonly HashSet<string> PrinterNames = new HashSet<string>
        {
            "jupiter", "neptune", "pangea", "mercury", "sonic"
        };

    public void Setup(string printerName)
    {
        if (!PrinterNames.Contains(printerName))
        {
            throw new ArgumentException("Unknown printer name", "printerName");
        }
        // ...
    }
}
Sergey Brunov
la source
1

J'ai cherché maintenant plus de 2h pour trouver un bon moyen de trouver des doublons dans une liste et comment les supprimer . Voici la réponse la plus simple:

//Copy the string array with the filtered data of the analytics db into an list
// a list should be easier to use
List<string> list_filtered_data = new List<string>(analytics_db_filtered_data);

// Get distinct elements and convert into a list again.
List<string> distinct = list_filtered_data.Distinct().ToList();

La sortie ressemblera à ceci: Les éléments dupliqués seront supprimés dans la nouvelle liste appelée distinct!

Ricardo Fercher
la source