Kiểm tra xem một giá trị có trong một mảng (C #) hay không


109

Làm cách nào để kiểm tra xem một giá trị có nằm trong một mảng trong C # hay không?

Giống như, tôi muốn tạo một mảng với danh sách tên máy in.

Chúng sẽ được cấp cho một phương thức, phương thức này sẽ lần lượt xem xét từng chuỗi và nếu chuỗi giống với một giá trị trong một mảng, hãy thực hiện hành động đó.

Ví dụ:

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

Đây là tên của các máy in, chúng đang được đưa vào phương thức PrinterSetup.

PrinterSetup sẽ giống như sau (một số mã giả):

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

Làm cách nào để định dạng if (printer == "jupiter")theo cách mà C # có thể nhận ra?


4
Hãy thử đặt tên tham số của bạn một kiểu (chuỗi) và nó sẽ ổn.
Jon Skeet

2
Tôi hơi bối rối với câu hỏi. Bạn đang hỏi làm thế nào để kiểm tra xem một giá trị có trong một mảng hay không hoặc làm cách nào để so sánh chuỗi trong C #? Nếu đó là cái sau, bạn sẽ sử dụng printer.Equals("jupiter"). Nếu đó là trước đây, sử dụng linqprinter.Contains("jupiter")
newfurniturey

@newfurniturey Khá là ... câu hỏi bị nhầm lẫn, mã ví dụ không khớp với tiêu đề và do đó các câu trả lời cũng bị nhầm lẫn; tại sao tào lao như thế này được ủng hộ là ngoài tôi. Và không cần phải làm gì printer.Equals("jupiter")... Mã của OP if (printer == "jupiter")hoạt động tốt ... miễn là printerđược khai báo là một chuỗi, như Skeet lưu ý.
Jim Balter

Câu trả lời:


231

Thêm không gian tên cần thiết

using System.Linq;

Sau đó, bạn có thể sử dụng Contains()phương pháp linq

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}

2
@ 0A0D. Câu trả lời này tôi nghĩ tốt nhất là cách đơn giản nhất / ngắn nhất và nổi tiếng để đạt được điều tương tự ( How do I check if a value is in an array in C#?) và hiệu quả. Không có vòng lặp không có phương pháp bổ sung. Chỉ có một không gian tên là thêm mà không phải là một điều lớn.
Sami

6
@Sami: Linq sử dụng vòng lặp trong nội bộ.

2
@ 0A0D Sam có lẽ đang đề cập đến mã được viết, không phải hướng dẫn được biên dịch. Linq sử dụng các vòng lặp và phương thức trong nội bộ, nhưng theo quan điểm của người lập trình, tất cả những gì được ẩn và không cần phải lo lắng.
Phát hành

1
Đúng @ 0A0D. Ý tôi là lập trình viên / nhà phát triển không cần phải lặp lại. Kiểm tra ngoài khóa học từ mảng cần một vòng lặp :)
Sami

3
Điều này chắc chắn là dễ dàng và được khuyến nghị. Nếu bạn không có quyền truy cập vào Linq, hoặc không muốn sử dụng Linq, bạn có thể dựa vào một số triển khai giao diện rõ ràng của mảng. Kể từ .NET 1.1, chúng tôi có ((IList)printer).Contains("Jupiter")nó không phải là chung chung (các loại giá trị hộp có thể, v.v.) và hoạt động ngay cả đối với các mảng đa chiều. Và kể từ khi .NET 2.0, chúng tôi có nhiều điều kỳ diệu ((IList<string>)printer).Contains("Jupiter")hơn, an toàn hơn. Phương pháp Linq là mới trong .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) Đúng 2) Sai 3) Đúng 4) Sai


6
Đây phải là câu trả lời được chấp nhận. Nếu bạn sử dụng một mảng, nó không hoàn toàn không xảy ra, hiệu suất đó không quan trọng. Trong trường hợp này, Linq thường là lựa chọn sai lầm.
Philm

22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  

Đây là một ví dụ chung - bạn có thể cung cấp một ví dụ phù hợp hơn với câu hỏi không?
kaz

9
Nó có thể là một ví dụ chung, nhưng đó chính xác là những gì tôi đang tìm kiếm.
Grant Birchmeier

7

Một cái gì đó như thế này?

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

7
    public static bool Contains(Array a, object val)
    {
        return Array.IndexOf(a, val) != -1;
    }

2
Tôi thích điều này. Tuy nhiên, nó sẽ không thành công nếu alà một mảng đa chiều (chẳng hạn như new string[10, 20, 15]), với một ngoại lệ. Nó cũng sẽ thất bại với các mảng một chiều không được lập chỉ mục từ 0 (chẳng hạn như Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, })hiếm gặp trong C #, tôi thừa nhận), với giá trị trả về có thể sai. Những thiếu sót rất dễ sửa chữa với Generics:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen

Tôi thích điều này, nhưng chỉ vì nó không có Linq và nó xác nhận rằng IndexOf là thứ duy nhất còn lại để sử dụng.
Bitterblue

6

Lưu ý: Câu hỏi là về mảng các chuỗi. Các quy trình đã đề cập không được trộn lẫn với phương thức .Contains của chuỗi đơn.

Tôi muốn thêm một câu trả lời mở rộng đề cập đến các phiên bản C # khác nhau và vì hai lý do:

  • Câu trả lời được chấp nhận yêu cầu Linq là C # thành ngữ hoàn hảo trong khi nó không đi kèm với chi phí và không có sẵn trong C # 2.0 trở xuống. Khi một mảng được tham gia, hiệu suất có thể quan trọng, vì vậy có những trường hợp bạn muốn ở lại với các phương thức Mảng.

  • Không có câu trả lời nào liên quan trực tiếp đến câu hỏi nơi nó được yêu cầu cũng đặt điều này trong một hàm (Vì một số câu trả lời cũng đang trộn các chuỗi với các mảng chuỗi, điều này không hoàn toàn không quan trọng).

Array.Exists () là một phương thức C # /. NET 2.0 và không cần Linq. Tìm kiếm trong mảng là O (n). Để truy cập nhanh hơn nữa, hãy sử dụng HashSet hoặc các bộ sưu tập tương tự.

Vì .NET 3.5 cũng tồn tại một phương thức chung 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");
   }
}

Bạn có thể viết một phương thức mở rộng riêng (C # 3.0 trở lên) để thêm đường cú pháp để có được ".Contains" giống / tương tự như đối với chuỗi cho tất cả các mảng mà không bao gồm 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));
}

Trong trường hợp này, ArrayContains()phương pháp này được sử dụng chứ không phải phương thức Chứa của Linq.

Các phương thức .Contains được đề cập ở nơi khác đề cập đến List<T>.Contains(kể từ C # 2.0) hoặc ArrayList.Contains(kể từ C # 1.1), nhưng không trực tiếp đến chính mảng.


1
Tôi đề nghị đổi tên thành ArrayContains () để tránh nhầm lẫn với Linq Contains ()
peter.cyc

Tôi đã làm điều này, mặc dù cũng có những lập luận phản đối: Ý tưởng cơ bản của tính đa hình là sử dụng cùng một tên cho các kiểu dữ liệu khác nhau, Đặc biệt là với thiết lập Linq. Sử dụng các tên khác nhau không phải là đa hình. Nhưng khả năng dễ đọc và tránh hiểu lầm sẽ chiến thắng, tôi nghĩ vậy, vâng.
Philm

4

Bạn chỉ thiếu một cái gì đó trong phương pháp của mình:

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

Chỉ cần thêm stringvà bạn sẽ ổn.


3

Không rõ vấn đề của bạn là gì, nhưng có vẻ như bạn muốn một cái gì đó như thế này:

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

    if( printer.Exists( p => p.Equals( "jupiter" ) ) )
    {
        ...
    }

2

Cân nhắc sử dụng HashSet<T>Class vì lợi ích của hiệu suất tra cứu:

Phương pháp này là một phép toán O (1).

- HashSet<T>.ContainsPhương pháp (T), MSDN .

Ví dụ:

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");
        }
        // ...
    }
}

1

Bây giờ tôi đã tìm kiếm hơn 2 giờ để tìm một cách độc đáo như thế nào để tìm các bản sao trong danh sách và cách xóa chúng . Đây là câu trả lời đơn giản nhất:

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

Đầu ra sẽ giống như sau: Các phần tử trùng lặp sẽ bị xóa trong danh sách mới được gọi là khác biệt!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.