Existe um operador C # IN?

89

No SQL, você pode usar a seguinte sintaxe:

SELECT *
FROM MY_TABLE
WHERE VALUE_1 IN (1, 2, 3)

Existe um equivalente em C #? O IDE parece reconhecer "in" como uma palavra-chave, mas não consigo encontrar nenhuma informação sobre ela.

Então, é possível fazer algo como o seguinte:

int myValue = 1;
if (myValue in (1, 2, 3))
    // Do something

Ao invés de

int myValue = 1;
if (myValue == 1 || myValue == 2 || myValue == 3)
    // Do something
Paul Michaels
fonte
Editei um pouco para esclarecer o que estava tentando comparar
Paul Michaels
verifique outra resposta adicionada por mim
Pranay Rana
Isso já foi perguntado várias vezes no stackoverflow ...
chiccodoro
3
@chiccodoro se esta pergunta foi feita antes, então sinalize como uma duplicata e poste uma resposta com o link para a pergunta original, não deixe apenas um comentário negativo
Hannish

Respostas:

125

Se você quiser escrever .In, poderá criar uma extensão que permita fazer isso.

static class Extensions
{

    public static bool In<T>(this T item, params T[] items)
    {
        if (items == null)
            throw new ArgumentNullException("items");

        return items.Contains(item);
    }

}


class Program
{

    static void Main()
    {


        int myValue = 1;

        if (myValue.In(1, 2, 3))
            // Do Somthing...

        string ds = "Bob";

        if (ds.In("andy", "joel", "matt")) 
        // Do Someting...
    }
}
Andy Robinson
fonte
1
Apenas lembre-se de adicionar usando System.Linq;
Tanner Ornelas
É muito melhor ler do que conter ... Mais fácil de entender
Konrad
84

List.Contains()é eu acho que você está procurando. C # tem in keyworde não um operatorpropósito completamente diferente daquele que você está se referindo no SQL.

Existem duas maneiras de usar inpalavras-chave em C #. Suponha que você tenha uma string [] ou Lista em C #.

        string[] names; //assume there are some names;

        //find all names that start with "a"
        var results = from str in names
                      where str.StartsWith("a")
                      select str;

        //iterate through all names in results and print
        foreach (string name in results)
        {
            Console.WriteLine(name);
        }

Referindo-se a sua edição, eu colocaria seu código desta forma para fazer o que você precisa.

        int myValue = 1;
        List<int> checkValues = new List<int> { 1, 2, 3 };

        if (checkValues.Contains(myValue))
            // Do something 
isto. __curious_geek
fonte
4
As pessoas veem o SQL e
vão
29

Você consegue fazer isso:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}
JwJosefy
fonte
2
Eu preferi esta resposta às mais votadas, pois o objetivo de querer fazer IN em vez de verificações de igualdade repetidas é reduzir a complexidade do código, e isso é bom, curto e simples!
MrVimes 01 de
1
Obrigado @MrVimes!
JwJosefy
7

Você geralmente usa o Containsmétodo de uma coleção.

myCollection.Where(p => Enumerable.Range(1,3).Contains(p));

Espero que ajude.

luckyyluke
fonte
6

Não há operador "in" em C #, a palavra-chave "in" é usada apenas com "foreach (... in ...)" ou "from ... in ...".

O equivalente LINQ de sua consulta SQL seria:

List<int> list = new List<int> { 1, 2, 3 };
var query = from row in my_table
            where list.Contains(row.value1)
            select row;
Daniel
fonte
4

Duplicado de: LINQ to SQL em e não em

select * from table where fieldname in ('val1', 'val2') 

ou

select * from table where fieldname not in (1, 2) 

O equivalente a consultas IN e NOT IN em LINQ to SQL seria algo assim:

List<string> validValues = new List<string>() { "val1", "val2"}; 
var qry = from item in dataContext.TableName 
          where validValues.Contains(item.FieldName) 
          select item; 

e isto:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 
Pranay Rana
fonte
Sim - desculpe, editei minha pergunta, pois o que estou perguntando não se relaciona a linq
Paul Michaels
4

Eu concordo que a melhor maneira de implementar o operador In é com um Método de Extensão. Eu fiz um pouco diferente:

public static bool In(this string str, string CommaDelimintedStringSet)
{
    string[] Values = CommaDelimintedStringSet.Split(new char[] { ',' });
    foreach (string V in Values)
    {
       if (str == V)
         return true;
    }
    return false;
}

A diferença é que você não precisa colocar aspas em torno de cada valor, apenas o conjunto inteiro de valores delimitados por vírgulas, que é mais fácil de digitar:

bool result = MyString.In("Val1,Val2,Val3");
Chuck Bevitt
fonte
Seria melhor utilizar param-arrays com esta função. Curta public static bool In(this string str, params string[] stringSet)e chame assimbool result = myString.In("Val1", "Val2", "Val3")
Manuel Hoffmann
2

Você pode escrever uma extensão. Eu escrevi um tempo atrás, para fazer código como

if(someObject.stringPropertyX.Equals("abc") || someObject.stringPropertyX.Equals("def") || ....){
    //do something
    ...
}else{
   //do something other...
   ....
}

mais legível com uma extensão que um era capaz de escrever

if(someObject.stringPropertyX.In("abc", "def",...,"xyz"){
   //do something
   ...
}else{
  //do something other...
  ....
}

Aqui está o código :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Some.Namespace.Extenders
{
    public static class StringExtender
    {
        /// <summary>
        /// Evaluates whether the String is contained in AT LEAST one of the passed values (i.e. similar to the "in" SQL clause)
        /// </summary>
        /// <param name="thisString"></param>
        /// <param name="values">list of strings used for comparison</param>
        /// <returns><c>true</c> if the string is contained in AT LEAST one of the passed values</returns>
        public static bool In(this String thisString, params string[] values)
        {
            foreach (string val in values)
            {
                if (thisString.Equals(val, StringComparison.InvariantCultureIgnoreCase))
                    return true;
            }

            return false; //no occurence found
        }
    }
}

Este é o específico para minhas necessidades naquele momento, mas você pode adaptá-lo e modificá-lo para corresponder a mais tipos diferentes.

Juri
fonte
2

Para dígitos de 0 a 9:

"123".Contains(myValue)

Para qualquer outra coisa:

"|1|2|3|".Contains("|" + myValue + "|")
user3354025
fonte
2

Para sua pergunta atualizada, você também pode usar uma instrução switch.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}
Pranay Rana
fonte
1
Isso é o que acabei fazendo. Suponho que o consenso é que não há realmente nenhuma facilidade para isso em C #.
Paul Michaels
5
Eu realmente não teria aceitado isso, porque NÃO é uma resposta à pergunta do operador "in". Em vez disso, veja a resposta mais votada ...
chiccodoro
6
Eu não recomendaria essa abordagem de forma alguma! Não é escalonável e tem a capacidade de tornar a vida de seus colegas programadores miserável!
deciclone
3
@decyclone: ​​Sim, é tudo uma questão de sustentabilidade. codifique como se o próximo programador a substituí-lo fosse um serial killer e soubesse onde você mora.
isso. __curious_geek
Eu discordo, não havia uma resposta real para a pergunta (ou a resposta era "não, isso não existe em C #") - então essa parecia a alternativa mais próxima para mim. Você também deve ter em mente que a pergunta foi baseada na funcionalidade da linguagem e não no estilo.
Paul Michaels
1

Não existe um operador in que procura um valor em uma coleção, ao invés disso é um método da coleção, chamado Contains.

A solução mais escalonável é usar um HashSetcomo coleção. A verificação de um valor em a HashSeté próxima de uma operação O (1), em comparação com fazê-lo em a Listonde é uma operação O (n). Isso significa que você pode empacotar muitos valores em a HashSete ainda assim é rápido, enquanto procurar um valor em a Listfica mais lento quanto mais valores você tem.

Exemplo:

var set = new HashSet<int>();
set.Add(1);
set.Add(2);
set.Add(3);

var result = items.Select(i => set.Contains(i.value));
Guffa
fonte
1

Comum, LINQ muito mais poderoso:

var list = new List<string> { "Tomato", "Orange", "Mango"};
var query = from i in my_table
            from v in list
            where i.Name.StartsWith(v)
            select i;
bjolfr
fonte
0

A inpalavra-chave em C # é para a foreachinstrução e para expressões de consulta LINQ. Não há funcionalidade equivalente ao inoperador SQL em C # per se, mas o LINQ oferece funcionalidade semelhante com Contains().

var list = {1, 2, 3}
var filtered = (
    from item in items
    where list.Contains(item)
    select item).ToArray().
P papai
fonte
0

Eu faço algo assim:

var shippingAddress = checkoutContext.Addresses.Where(a => (new HashSet<AddressType> { AddressType.SHIPPING_ONLY, AddressType.BILLING_AND_SHIPPING }).Contains(a.AddressType) && a.Id == long.Parse(orderDto.ShippingAddressId)).FirstOrDefault();
BRBdot
fonte