Verifique se um valor está em uma matriz (C #)

109

Como posso verificar se um valor está em uma matriz em C #?

Tipo, eu quero criar um array com uma lista de nomes de impressoras.

Eles serão alimentados para um método, que examinará cada string por vez, e se a string for igual a um valor em um array, faça essa ação.

Por exemplo:

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

Esses são os nomes das impressoras, eles estão sendo alimentados pelo método PrinterSetup.

PrinterSetup será mais ou menos assim (algum pseudocódigo):

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

Como faço para formatar if (printer == "jupiter")de uma maneira que o C # possa reconhecer?

Cecil Rodriguez
fonte
4
Tente dar ao seu nome de parâmetro um tipo (string) e tudo ficará bem.
Jon Skeet
2
Estou meio confuso quanto à pergunta. Você está perguntando como verificar se um valor está em uma matriz ou como fazer uma comparação de strings em C #? Se for o último, você usaria printer.Equals("jupiter"). Se for o primeiro, use linqeprinter.Contains("jupiter")
newfurniturey
@newfurniturey Exatamente ... a pergunta é confusa, o código de exemplo não corresponde ao título e, portanto, as respostas também são confusas; por que merdas como essa são votadas está além de mim. E não há necessidade de fazer printer.Equals("jupiter")... O código do OP if (printer == "jupiter")funciona muito bem ... desde que printerseja declarado como uma string, como observa Skeet.
Jim Balter

Respostas:

231

Adicione o namespace necessário

using System.Linq;

Então você pode usar o Contains()método linq

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}
Dmytro
fonte
2
@ 0A0D. Acho que essa resposta é a mais simples / curta e bem conhecida maneira de conseguir a mesma coisa ( How do I check if a value is in an array in C#?) e também eficiente. Sem loop, nenhum método extra. Apenas um namespace é extra, o que não é grande coisa.
Sami
6
@Sami: Linq usa loops internamente.
2
@ 0A0D Sam provavelmente está se referindo a código escrito, não a instruções compiladas. O Linq usa loops e métodos internamente, mas do ponto de vista dos codificadores, tudo o que está escondido e não precisa se preocupar.
Trisped em
1
Direita @ 0A0D. Eu quis dizer que o codificador / desenvolvedor não precisa fazer um loop correto. A verificação de curso da matriz precisa de um loop :)
Sami
3
Certamente, isso é fácil e recomendável. Se você não tiver acesso ao Linq ou não quiser usar o Linq, pode contar com alguma implementação de interface explícita do array. Desde .NET 1.1 temos o ((IList)printer).Contains("Jupiter")que é não genérico (pode incluir tipos de valor, etc.) e funciona até mesmo para arrays multidimensionais. E desde o .NET 2.0, temos o mais mágico, ((IList<string>)printer).Contains("Jupiter")que é mais seguro para tipos. A abordagem do Linq era nova no .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) Verdadeiro 2) Falso 3) Verdadeiro 4) Falso


fonte
6
Esta deve ser a resposta aceita. Se você usar uma matriz, não é totalmente improvável, que o desempenho importa. Nesse caso, o Linq costuma ser a escolha errada.
Philm
22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  
Convidado
fonte
Este é um exemplo geral - você pode fornecer um que corresponda melhor à pergunta?
kaz de
9
Pode ser um exemplo geral, mas é exatamente o que eu procurava.
Grant Birchmeier
7

Algo assim?

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
fonte
7
    public static bool Contains(Array a, object val)
    {
        return Array.IndexOf(a, val) != -1;
    }
Raz Megrelidze
fonte
2
Eu gosto disso. No entanto, ele falhará se afor uma matriz multidimensional (como new string[10, 20, 15]por exemplo), com uma exceção. Ele também falhará com matrizes unidimensionais que não são indexadas a partir de zero (como Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, }), raro em C #, admito), com um valor de retorno possivelmente errado. Essas deficiências são fáceis de corrigir com genéricos:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen
Eu gosto disso, mas apenas porque é sem Linq e confirma que IndexOf é a única coisa que resta para usar.
Bitterblue
6

Nota: a questão é sobre matrizes de strings. As rotinas mencionadas não devem ser misturadas com o método .Contains de strings únicas.

Eu gostaria de adicionar uma resposta extensa referindo-se a diferentes versões C # e por dois motivos:

  • A resposta aceita requer Linq, que é perfeitamente idiomático C #, embora não venha sem custos e não esteja disponível em C # 2.0 ou inferior. Quando um array está envolvido, o desempenho pode ser importante, portanto, há situações em que você deseja permanecer com os métodos Array.

  • Nenhuma resposta atende diretamente à pergunta onde foi solicitado também colocar isso em uma função (como algumas respostas também misturam strings com matrizes de strings, isso não é completamente sem importância).

Array.Exists () é um método C # /. NET 2.0 e não precisa de Linq. Pesquisar em matrizes é O (n). Para um acesso ainda mais rápido, use HashSet ou coleções semelhantes.

Desde .NET 3.5 também existe um método genérico 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");
   }
}

Você poderia escrever um método de extensão próprio (C # 3.0 e superior) para adicionar o açúcar sintático para obter o mesmo / semelhante ".Contains" como para strings para todos os arrays sem incluir 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));
}

Neste caso, este ArrayContains()método é usado e não o método Contains do Linq.

Os outros métodos mencionados .Contains referem-se a List<T>.Contains(desde C # 2.0) ou ArrayList.Contains(desde C # 1.1), mas não a arrays diretamente.

Philm
fonte
1
Eu sugiro mudar o nome para ArrayContains () para evitar confusão com Linq Contains ()
peter.cyc
Eu fiz isso, embora também haja argumentos contra: É a ideia básica do polimorfismo usar o mesmo nome para diferentes tipos de dados, especialmente com uma configuração do Linq em mente. Usar nomes diferentes não é polimorfo. Mas a legibilidade e a prevenção de mal-entendidos devem vencer, eu acho, então, sim.
Film
4

Você está simplesmente perdendo algo em seu método:

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

Basta adicionar stringe você ficará bem.


fonte
3

Não está muito claro qual é o seu problema, mas parece que você quer algo assim:

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

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

Considere o uso de HashSet<T>Class para o desempenho da pesquisa:

Este método é uma operação O (1).

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

Por exemplo:

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
fonte
1

Pesquisei agora por 2h para encontrar uma maneira agradável de encontrar duplicatas em uma lista e como removê-las . Aqui está a resposta mais simples:

//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();

A saída terá a seguinte aparência: Elementos duplicados serão removidos da nova lista chamada distintos!

Ricardo Fercher
fonte