มีตัวดำเนินการ C # IN หรือไม่?


91

ใน SQL คุณสามารถใช้ไวยากรณ์ต่อไปนี้:

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

มี C # เทียบเท่าหรือไม่? ดูเหมือนว่า IDE จะรู้จักคำว่า "in" แต่ดูเหมือนว่าฉันจะไม่พบข้อมูลใด ๆ

เป็นไปได้ไหมที่จะทำสิ่งต่อไปนี้:

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

แทน

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

ฉันแก้ไขสิ่งนี้เล็กน้อยเพื่อชี้แจงสิ่งที่ฉันพยายามเปรียบเทียบ
Paul Michaels

ตรวจสอบคำตอบอื่นที่เพิ่มโดยฉัน
Pranay Rana

สิ่งนี้ถูกถามหลายครั้งแล้วใน stackoverflow ...
chiccodoro

3
@chiccodoro หากมีการถามคำถามนี้ก่อนแล้วให้ตั้งค่าสถานะว่าซ้ำกันและโพสต์คำตอบพร้อมลิงก์ไปยังคำถามเดิมอย่าเพิ่งแสดงความคิดเห็นเชิงลบ
Hannish

คำตอบ:


129

หากคุณต้องการเขียนในนั้นคุณสามารถสร้างส่วนขยายที่ช่วยให้คุณทำเช่นนั้นได้

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

2
อย่าลืมเพิ่มโดยใช้ System.Linq;
Tanner Ornelas

1
In นั้นอ่านได้ดีกว่ามีมาก ... เข้าใจง่ายกว่า
Konrad

85

List.Contains()ฉันคิดว่าคุณกำลังมองหาอะไรอยู่ C # มีin keywordและไม่มีoperatorจุดประสงค์ที่แตกต่างกันโดยสิ้นเชิงจากนั้นสิ่งที่คุณอ้างถึงใน SQL

มีสองวิธีที่คุณสามารถใช้inคำสำคัญใน C # สมมติว่าคุณมีสตริง [] หรือรายการใน 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);
        }

อ้างถึงการแก้ไขของคุณฉันจะใส่โค้ดของคุณเพื่อทำสิ่งที่คุณต้องการ

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

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

4
ผู้คนเห็น SQL และข้ามไปที่ LINQ ทันที แต่ฟังก์ชันง่ายๆนี้อาจเป็นสิ่งที่เขาต้องการ
Bart van Heukelom

31

คุณสามารถทำได้:

var x = 99; // searched value

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

2
ฉันชอบคำตอบนี้สำหรับคนที่ได้รับการโหวตที่สูงกว่าเนื่องจากจุดรวมของการต้องการทำ IN แทนการตรวจสอบความเท่าเทียมกันซ้ำ ๆ คือการลดความซับซ้อนของโค้ดและนี่เป็นสิ่งที่ดีและสั้นและเรียบง่าย!
MrVimes

7

คุณมักจะใช้Containsวิธีการรวบรวม

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

ฉันหวังว่ามันจะช่วยได้


6

ไม่มีตัวดำเนินการ "in" ใน C # คำหลัก "in" จะใช้กับ "foreach (... in ... )" หรือ "from ... in ... " เท่านั้น

LINQ เทียบเท่ากับแบบสอบถาม SQL ของคุณคือ:

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

4

ซ้ำกันของ: LINQ เป็น SQL ในและไม่อยู่ใน

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

หรือ

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

คำสั่ง IN และ NOT IN ที่เทียบเท่าใน LINQ ถึง SQL จะเป็นดังนี้:

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

และนี่:

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

ใช่ - ขอโทษฉันแก้ไขคำถามแล้วเนื่องจากสิ่งที่ฉันถามไม่เกี่ยวข้องกับ linq
Paul Michaels

4

ฉันเห็นด้วยวิธีที่ดีที่สุดในการใช้ตัวดำเนินการ In คือการใช้วิธีการขยาย ฉันทำมันแตกต่างกันเล็กน้อย:

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

ความแตกต่างคือคุณไม่จำเป็นต้องใส่เครื่องหมายคำพูดรอบ ๆ แต่ละค่ามีเพียงชุดค่าที่คั่นด้วยจุลภาคทั้งหมดซึ่งง่ายต่อการพิมพ์:

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

มันจะเป็นการดีกว่าที่จะใช้พารา - อาร์เรย์กับฟังก์ชันนี้ ชอบpublic static bool In(this string str, params string[] stringSet)และเรียกมันว่าbool result = myString.In("Val1", "Val2", "Val3")
Manuel Hoffmann

2

คุณสามารถเขียนนามสกุล ฉันเขียนครั้งหนึ่งที่ผ่านมาสำหรับการสร้างรหัสเช่น

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

สามารถอ่านได้มากขึ้นด้วยส่วนขยายที่สามารถเขียนได้

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

นี่คือรหัส :

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

นี่เป็นสิ่งที่เฉพาะเจาะจงสำหรับความต้องการของฉันในเวลานั้น แต่คุณสามารถปรับเปลี่ยนและแก้ไขให้เข้ากับประเภทต่างๆ


2

สำหรับตัวเลขตั้งแต่ 0 ถึง 9:

"123".Contains(myValue)

สำหรับสิ่งอื่น ๆ :

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

2

สำหรับคำถามที่อัปเดตของคุณคุณสามารถใช้คำสั่ง switch ได้เช่นกัน

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

1
นี่คือสิ่งที่ฉันทำ ฉันคิดว่าฉันทามติคือไม่มีสิ่งอำนวยความสะดวกสำหรับสิ่งนี้ใน C #
Paul Michaels

5
ฉันคงไม่ยอมรับสิ่งนี้จริงๆเพราะมันไม่ใช่คำตอบสำหรับคำถามตัวดำเนินการ "ใน" ดูคำตอบที่ได้รับการโหวตสูงสุดแทน ...
chiccodoro

6
ฉันไม่อยากแนะนำวิธีนี้เลย! มันไม่สามารถปรับขนาดได้และมีความสามารถในการทำให้ชีวิตของเพื่อนโปรแกรมเมอร์ของคุณเป็นทุกข์!
decyclone

3
@decyclone: ​​ใช่ทุกอย่างเกี่ยวกับการบำรุงรักษา รหัสราวกับว่าโปรแกรมเมอร์คนต่อไปที่จะมาแทนที่คุณคือฆาตกรต่อเนื่องและรู้ว่าคุณอาศัยอยู่ที่ไหน
นี่ __curious_geek

ฉันไม่เห็นด้วยไม่มีคำตอบที่แท้จริงสำหรับคำถาม (หรือคำตอบคือ "ไม่นั่นไม่มีอยู่ใน C #") ดังนั้นนี่จึงดูเหมือนเป็นทางเลือกที่ใกล้เคียงที่สุดสำหรับฉัน คุณต้องจำไว้ด้วยว่าคำถามนั้นขึ้นอยู่กับฟังก์ชันการทำงานของภาษาไม่ใช่รูปแบบ
Paul Michaels

1

Containsไม่มีในผู้ประกอบการที่จะมองหาค่าในคอลเลกชันแทนมันเป็นวิธีการของคอลเลกชันที่เรียกว่า

โซลูชันที่ปรับขนาดได้มากที่สุดคือการใช้ไฟล์ HashSetเป็นคอลเลกชัน การตรวจสอบค่าใน a HashSetนั้นใกล้เคียงกับการดำเนินการ O (1) เมื่อเทียบกับการดำเนินการในListตำแหน่งที่เป็นการดำเนินการ O (n) นั่นหมายความว่าคุณสามารถบรรจุค่าได้มากใน a HashSetและยังเร็วในขณะที่มองหาค่าในไฟล์Listช้าลงยิ่งคุณมีค่ามากขึ้น

ตัวอย่าง:

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

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

1

ทั่วไปวิธี LINQ มีประสิทธิภาพมากขึ้น:

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

inคำหลักใน C # สำหรับforeachคำสั่งและการแสดงออก LINQ แบบสอบถาม ไม่มีฟังก์ชันการทำงานที่เทียบเท่ากับinตัวดำเนินการของ SQL ใน C # per se แต่ LINQ มีฟังก์ชันการทำงานที่คล้ายกันกับContains().

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

0

ฉันทำสิ่งนี้:

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();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.