¿Existe un operador C # IN?


91

En SQL, puede utilizar la siguiente sintaxis:

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

¿Existe un equivalente en C #? El IDE parece reconocer "in" como palabra clave, pero no parece que pueda encontrar ninguna información sobre él.

Entonces, ¿es posible hacer algo como lo siguiente:

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

En vez de

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

He editado esto un poco para aclarar lo que estaba tratando de comparar
— Paul Michaels

verifique otra respuesta agregada por mí
— Pranay Rana

Esto ya se ha preguntado varias veces en stackoverflow ...
— chiccodoro

3
@chiccodoro si esta pregunta se ha hecho antes, márquela como un duplicado y publique una respuesta con el enlace a la pregunta original, no deje un comentario negativo
— Hannish

Respuestas:


128

Si quisiera escribir .In, entonces podría crear una extensión que le permita hacerlo.

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...
    }
}

1
Solo recuerde agregar usando System.Linq;
— Tanner Ornelas

Es mucho mejor leer que contiene ... Más fácil de entender
— Konrad

85

List.Contains()creo que lo que estás buscando. C # tienein keyword y no tiene un operatorpropósito completamente diferente al que se refiere en SQL.

Hay dos formas de usar inpalabras clave en C #. Suponga que tiene una cadena [] o Lista en 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);
        }

Refiriendo su edición, pondría su código de esta manera para hacer lo que necesita.

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

        if (checkValues.Contains(myValue))
            // Do something 

4
La gente ve SQL y salta instantáneamente a LINQ, pero esta función simple es probablemente exactamente lo que él quiere
— Bart van Heukelom

30

Puedes hacerlo:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}

2
Preferí esta respuesta a las más votadas, ya que el objetivo de querer hacer IN en lugar de verificaciones de igualdad repetidas es reducir la complejidad del código, ¡y esto es agradable, corto y simple!
— MrVimes

7

Suele utilizar el Containsmétodo de una colección.

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

Espero que ayude.


6

No hay un operador "in" en C #, la palabra clave "in" se usa solo con "foreach (... in ...)" o "from ... in ...".

El equivalente LINQ de su consulta SQL sería:

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

4

Duplicado de: LINQ to SQL en y no en

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

o

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

El equivalente de consultas IN y NOT IN en LINQ to SQL sería algo como esto:

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

y esto:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 

Sí, lo siento, he editado mi pregunta, ya que lo que estoy preguntando no se relaciona con linq
— Paul Michaels

4

Estoy de acuerdo en que la mejor manera de implementar el operador In es con un método de extensión. Lo hice un poco 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;
}

La diferencia es que no tiene que poner comillas alrededor de cada valor, solo el conjunto completo de valores delimitados por comas, que es más fácil de escribir:

bool result = MyString.In("Val1,Val2,Val3");

Sería mejor utilizar param-arrays con esta función. Me gusta public static bool In(this string str, params string[] stringSet)y llámalo comobool result = myString.In("Val1", "Val2", "Val3")
— Manuel Hoffmann

2

Puede escribir una extensión. Escribí hace una vez, para hacer código como

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

más legible con una extensión en la que uno podía escribir

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

Aquí está el 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 es el específico para mis necesidades en ese momento, pero puede adaptarlo y modificarlo para que coincida con más tipos diferentes.


2

Para dígitos del 0 al 9:

"123".Contains(myValue)

Para cualquier otra cosa:

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

2

Para su pregunta actualizada, también puede usar una declaración de cambio.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}

1
Esto es lo que terminé haciendo. Supongo que el consenso es que realmente no hay ninguna facilidad para esto en C #.
— Paul Michaels

5
Realmente no habría aceptado esto, porque NO es una respuesta a la pregunta del operador "in". En su lugar, vea la respuesta más votada ...
— chiccodoro

6
¡No recomendaría este enfoque en absoluto! No es escalable y tiene la capacidad de hacer miserable la vida de sus compañeros programadores.
— deciclón

3
@decyclone: ​​Sí, se trata de mantenibilidad. codifique como si el próximo programador que lo reemplace fuera un asesino en serie y supiera dónde vive.
— esto. __curious_geek

No estoy de acuerdo, no hubo una respuesta real a la pregunta (o la respuesta fue "no, eso no existe en C #"), por lo que esta me pareció la alternativa más cercana. También hay que tener en cuenta que la pregunta se basó en la funcionalidad del lenguaje y no en el estilo.
— Paul Michaels

1

No hay un operador in que busque un valor en una colección, sino que es un método de la colección, llamado Contains.

La solución más escalable es utilizar a HashSetcomo colección. Comprobando un valor en unHashSet está cerca de una operación O (1), en comparación con hacerlo en a Listdonde es una operación O (n). Eso significa que puede empaquetar muchos valores en a HashSety aún así es rápido, mientras busca un valor en unList vuelve más lento cuanto más valores tiene.

Ejemplo:

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

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

1

Común, LINQ mucho más potente:

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;

0

La inpalabra clave en C # es para la foreachdeclaración y para las expresiones de consulta LINQ. No existe una funcionalidad equivalente al inoperador de SQL en C # per se, pero LINQ ofrece una funcionalidad similar con Contains().

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

0

Hago algo como esto:

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();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.